gdb breakpoint on base class, but failed - mongodb

in mongodb, class cursor is defined as 'Cursor : boost::noncopyable', and then there are many class which are derived from it. I want to know for a given operation from client, which XXXCursor was used. so I want to set a breakpoint on Cursor::Cursor. but failed.
(gdb) b mongo::Cursor::Cursor
the class mongo::Cursor does not have any method named Cursor
Hint: try 'mongo::Cursor::Cursor<TAB> or 'mongo::Cursor::Cursor<ESC-?>
(Note leading single quote.)
Make breakpoint pending on future shared library load? (y or [n]) n
(gdb) ptype mongo::Cursor
type = class mongo::Cursor : private boost::noncopyable_::noncopyable {
public:
~Cursor(int);
virtual bool ok(void);
bool eof(void);
virtual mongo::Record * _current(void);
virtual mongo::BSONObj current(void);
virtual mongo::DiskLoc currLoc(void);
virtual bool advance(void);
virtual mongo::BSONObj currKey(void) const;
....
}
(gdb) list mongo::Cursor::Cursor
**the class mongo::Cursor does not have any method named Cursor
Hint: try 'mongo::Cursor::Cursor<TAB> or 'mongo::Cursor::Cursor<ESC-?>**
(Note leading single quote.)
But I wrote a similar program
#include <iostream>
#include <boost/utility.hpp>
class Base : boost::noncopyable {
public:
void printx() {std::cout<< getx() <<"\n" ;}
virtual int getx()=0;
};
class P : public Base {
public:
int x;
virtual int getx() { return x*3;}
P(int c){ x= c;}
};
int main(){
P p(2);
p.printx();
return 0;
}
I can set breakpoint on Base::Base sucessfully.
do you have any idea why I can't set breakpoint on mongo::Cursor::Cursor ?
mongo::Cursor was definied here: https://github.com/mongodb/mongo/blob/master/src/mongo/db/cursor.h

As for your example. If I compile it like this:
g++ -O0 -g -m64 -I ./boost_1_53_0 main.cpp
I can set a breakpoint on Base::Base and I see Base::Base as a symbol:
>nm -C a.out | grep Base::Base
0000000000400a4e W Base::Base()
If I compile compile it like this (with optimization level O2):
g++ -O2 -g -m64 -I ./boost_1_53_0 main.cpp
I don't see Base::Base as a symbol:
>nm -C a.out | grep Base::Base
>
And can't set a breakpoint:
(gdb) b Base::Base
the class Base does not have any method named Base
Hint: try 'Base::Base<TAB> or 'Base::Base<ESC-?>
So as a first step make sure that there is mongo::Cursor::Cursor as a symbol in your program or shared library. It can be optimized out.

Related

Is it possible to invoke win32 call in windbg?

I'm trying to invoke win32 api with windbg,
> .call kernel32!ExitProcess(0)
^ Symbol not a function in '.call kernel32!ExitProcess(0)'
windbg should support this, any idea?
One reason might be that the debugger cannot find the method:
0:004> x kernel32!Exit*
00007ffc`12e9b0c0 KERNEL32!ExitVDM (<no parameter info>)
00007ffc`12e7d620 KERNEL32!ExitProcessImplementation (<no parameter info>)
You certainly don't have private symbols for kernel32!ExitProcess(). If you don't have the private symbols, then you need to have a function in your own code (for which you have private symbols) that you can pass as the prototype:
.call /s SameSignatureAsExitProcess kernel32!ExitProcess(0)
So what I would suggest is: get the LLD extension, compile yourself some methods like
Header file:
#pragma once
#include <Windows.h>
class Call
{
public:
static void v();
static void vi(int);
static void vui(unsigned int);
static void vl(long);
static void vul(unsigned long);
};
Cpp file:
#include "Call.h"
void Call::v(){}
void Call::vi(int) {}
void Call::vui(unsigned int) {}
void Call::vl(long) {}
void Call::vul(unsigned long) {}
and then use it
0:000> .load ...\lld
0:000> !injectdll ...\Calls\x64\Debug\Calls.dll
ModLoad: 00007ffc`11270000 00007ffc`1129e000 C:\Windows\System32\IMM32.DLL
ModLoad: 00007ffc`070a0000 00007ffc`070c5000 ...\Calls\x64\Debug\Calls.dll
ModLoad: 00007ffb`f9000000 00007ffb`f91c2000 C:\Windows\System32\ucrtbased.dll
ModLoad: 00007ffc`07070000 00007ffc`07092000 C:\Windows\System32\VCRUNTIME140D.dll
ModLoad: 00007ffc`0d800000 00007ffc`0d89c000 C:\Windows\system32\uxtheme.dll
ntdll!NtTerminateThread+0x14:
00007ffc`138f01c4 c3 ret
0:004> ld Calls
*** WARNING: Unable to verify checksum for ...\Calls\x64\Debug\Calls.dll
Symbols loaded for Calls
0:004> x Calls!Call::*
00007ffc`070b1710 Calls!Call::vui (unsigned int)
00007ffc`070b1760 Calls!Call::vul (unsigned long)
00007ffc`070b1670 Calls!Call::vi (int)
00007ffc`070b1620 Calls!Call::v (void)
00007ffc`070b16c0 Calls!Call::vl (long)
0:004> .call /s Calls!Call::v kernelbase!TerminateProcess()
Thread is set up for call, 'g' will execute.
WARNING: This can have serious side-effects,
including deadlocks and corruption of the debuggee.
While this looks much better (no error message), it still does not work - the process does not terminate. I currently can't figure out why. Maybe it's still helpful for someone.
What works for me is
static void t(); // .h
void Call::t() // .cpp
{
ExitProcess(0);
}
and then
0:007> .call Calls!Call::t()
Thread is set up for call, 'g' will execute.
WARNING: This can have serious side-effects,
including deadlocks and corruption of the debuggee.
0:007> p
Calls!Call::t+0x2a:
00007ffc`0709166a 33c9 xor ecx,ecx
0:007> p
ntdll!NtTerminateProcess+0x14:
00007ffc`138efce4 c3 ret
but that's not very convenient, if you don't know in advance what method you want to call.

fopen() in S-Function: compilation error [duplicate]

I declared a variable in this way:
int i = 0;
I get the warning:
ISO C90 forbids mixed declarations and code
How can I fix it?
I think you should move the variable declaration to top of block. I.e.
{
foo();
int i = 0;
bar();
}
to
{
int i = 0;
foo();
bar();
}
Up until the C99 standard, all declarations had to come before any statements in a block:
void foo()
{
int i, j;
double k;
char *c;
// code
if (c)
{
int m, n;
// more code
}
// etc.
}
C99 allowed for mixing declarations and statements (like C++). Many compilers still default to C89, and some compilers (such as Microsoft's) don't support C99 at all.
So, you will need to do the following:
Determine if your compiler supports C99 or later; if it does, configure it so that it's compiling C99 instead of C89;
If your compiler doesn't support C99 or later, you will either need to find a different compiler that does support it, or rewrite your code so that all declarations come before any statements within the block.
Just use a compiler (or provide it with the arguments it needs) such that it compiles for a more recent version of the C standard, C99 or C11. E.g for the GCC family of compilers that would be -std=c99.
Make sure the variable is on the top part of the block, and in case you compile it with -ansi-pedantic, make sure it looks like this:
function() {
int i;
i = 0;
someCode();
}
To diagnose what really triggers the error, I would first try to remove = 0
If the error is tripped, then most likely the declaration goes after the code.
If no error, then it may be related to a C-standard enforcement/compile flags OR ...something else.
In any case, declare the variable in the beginning of the current scope. You may then initialize it separately. Indeed, if this variable deserves its own scope - delimit its definition in {}.
If the OP could clarify the context, then a more directed response would follow.
-Wdeclaration-after-statement minimal reproducible example
main.c
#!/usr/bin/env bash
set -eux
cat << EOF > main.c
#include <stdio.h>
int main(void) {
puts("hello");
int a = 1;
printf("%d\n", a);
return 0;
}
EOF
Give warning:
gcc -std=c89 -Wdeclaration-after-statement -Werror main.c
gcc -std=c99 -Wdeclaration-after-statement -Werror main.c
gcc -std=c89 -pedantic -Werror main.c
Don't give warning:
gcc -std=c89 -pedantic -Wno-declaration-after-statement -Werror main.c
gcc -std=c89 -Wno-declaration-after-statement -Werror main.c
gcc -std=c99 -pedantic -Werror main.c
gcc -std=c89 -Wall -Wextra -Werror main.c
# https://stackoverflow.com/questions/14737104/what-is-the-default-c-mode-for-the-current-gcc-especially-on-ubuntu/53063656#53063656
gcc -pedantic -Werror main.c
The warning:
main.c: In function ‘main’:
main.c:5:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
int a = 1;
^~~
Tested on Ubuntu 16.04, GCC 6.4.0.
Ensure you made your declarations before any statements in the block.
For instance:
{
int i = 0;
printf("a string");/*the code is not a working code*/
}
I believe this should be helpful:
https://www.configrouter.com/iso-c90-forbids-mixed-declarations-and-code-in-c-30621/

How to force g++ to create C symbol name

I have a function called init in a cpp file, but when I compile it, g++ creates in the object file a symbol named _Z4initv, so when I link after with ld with the option -e init, obviously ld doesn't recognize the symbol init. Is there a way to create symbols name in C style with g++ ?
If you have a definition like e.g.
void init() { ... /* some code */ ... }
Then to inhibit name mangling you need to declare it as extern "C":
extern "C" void init() { ... /* some code */ ... }
If you have a declaration in a header file that you want to include in a C source file you need to check if you're including the header file in a C or C++ source file, using the __cplusplus macro:
#ifdef __cplusplus
extern "C"
#endif
void init(void);
Note that the function in the header file has to be declared with void in the argument list, if it doesn't take any arguments. That's because the declaration void init() means something else in C.

How can I import other files in Vala?

The question pretty much says it all- how could I import file2.vala to file1.vala?
You don't do it directly. If you run valac file1.vala file2.vala, it is as if you compiled them in one big file.
If you want to make them reusable, then you probably want a shared library. In which case, you compile one to produce a C header file and a VAPI definition:
valac --vapi file1.vapi -H file1.h --library libfile1.so file1.vala
The second one can then consume this:
valac --pkg file1 file2.vala
This assume that the VAPI file has been installed. If this is not the case, you'll need to pass --vapidir and the location where file1.vapi exists, probably .. Similarly, you'll need to inform the C compiler about where file1.h lives with -X -I/directory/containing, again, probably -X -I.. Finally, you'll need to tell the C linker where libfile1.so is via -X -L/directory/containing -X -lfile1. This is a little platform specific, and you can smooth the difference out using AutoMake, though this is a bit more involved. Ragel is the usual go-to project for how to use AutoMake with Vala.
just to supply apmasell:
you can use multiple files by using classes and public variables:
main.vala:
extern void cfunction(string text);
void main ()
{
first f = new first ();
f.say_something(f.mytext);
cfunction("c text\n");
}
class.vala:
public class first {
public string mytext = "yolo\n";
public first ()
{
stdout.printf("text from constructer in first\n");
}
public void say_something(string text)
{
stdout.printf("%s\n", text);
}
}
text.c:
#include <stdio.h>
void cfunction(const char *s)
{
puts("This is C code");
printf("%s\n", s);
}
compiles with: valac class.vala main.vala text.c
as you can see, you can even use C code

warning: XXXX has different visibility (default) in YYYY and (hidden) in ZZZZ

I am trying to make an iPhone app that uses OpenCV plus another C++ Library.
It seems to compile and link fine. It actually works.
Is just I want to get rid of this ugly warning:
ld: warning: std::vector<int, std::allocator<int> >::_M_insert_aux(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int const&)has different visibility (default) in /Users/nacho4d/Documents/Projects/iOS/iAR/opencv_device/lib/libcxcore.a(cxdatastructs.o) and (hidden) in /Users/nacho4d/Documents/Projects/iOS/iAR/build/iAR.build/Debug-iphoneos/iAR.build/Objects-normal/armv6/combination.o
What does it mean?, How can I solve it?
just in case, this is the header of combination class, from the library I mentioned.
//combination.h
typedef std::vector<int> combi;
typedef std::vector< combi > allcombi;
class Combination
{
public:
void Init(const int n, const int m);
allcombi::iterator begin();
allcombi::iterator end();
allcombi::const_iterator begin() const;
allcombi::const_iterator end() const;
private:
void Nest(int nest, int column, int n1, int n2, int k[], allcombi &result);
private:
allcombi m_data;
};
Thanks in advance
Ignacio
It seems libcxcore.a and combination.o are compiled with different symbol visibility options.
Read about symbol visibility there.
So, I guess you just need to compile combination.cpp with -fvisibility=default flag. If you use XCode, check "Symbols Hidden by Default" setting in "GCC - Code Generation" section. It should be unchecked for both projects.