I need to print the name of the called functions of a program using gcc plugins
for this I created a pass that will be called after ssa pass, I already initiated the plugin and I can loop on its statements, using a gimple_stmt_iterator :
int read_calls(){
unsigned i;
const_tree str, op;
basic_block bb;
gimple stmt;
tree fnt;
FOR_EACH_BB_FN(bb, cfun) {
gimple_stmt_iterator gsi;
for (gsi=gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi))
{
stmt = gsi_stmt(gsi);
if (is_gimple_call(stmt)){
const char* name = THE_FUNCTION_I_NEED(stmt);
cerr << " Function : " << name << " is called \n";
}
}
}
return 0;
}
How can I print the name of the called function using its gimple node ??
Can I also print other informations like the line number where it was called, the name of the function where it was called etc .. ?
I've been looking for the answer for hours, the answer is actually pretty easy :
get_name(tree node)... I've been trying many functions since the documentation is really poor... I found it here :
GCC Middle and Back End API Reference
As you can see, there is no comments about what the functions does, and it quit the best documentation I found about gcc, anyway get_name(..) is working fine, bit I haven't find how to print the source line yet
I know three ways:
1:
tree current_fn_decl = gimple_call_fndecl(stmt);
const char* name = function_name(DECL_STRUCT_FUNCTION(current_fn_decl);
2:
const char* name = IDENTIFIER_POINTER(DECL_NAME(current_fn_decl));
3:
tree current_fn_decl = gimple_call_fndecl(stmt);
const char* name = get_name(current_fn_decl);
Related
Problem Description:
I have created a custom C++ function print() that is supposed to be pushed as a global onto a table to so the user can use the print() function to print to the debug console. This function works to some extent, however, when you try to print a string with a space in it (over one word) the function is not called at all... This has greatly confused me, as I don't know why. If I were to try and call something such as print("Hello!") the console will have "Hello!" printed to it, but if I were to try and print something such as print("Hello world!") the function will not be called at all, I know this because I have used a message box to alert when the function is called.
Additional Information:
So, the closest thing to this I could find was a question asking how to make a custom print function in C++ with the Lua C API then push it onto the global table. I can already do this, and my function works to some extent. My function isn't being pushed onto the Lua C API's global table, instead to a table that is created by me with lua_newtable(L, s);. However, I've tried it both ways and it makes no difference. This print function does not support tables nor function as of now, I'm just focused on finding out and fixing why the function can't print strings over one word. Just in case you were wondering, Lua v5.1.5 and Microsoft Visual Studio 2017 are used for this. Debug mode, x86.
Code (C++):
If anyone could help me fix this, that would be great!
#include <iostream>
#include <string>
#include <Windows.h>
#pragma comment(lib, "Lua.lib")
#include "lua.hpp"
#include "luaconf.h"
static int print(lua_State* LUASTATE)
{
MessageBoxA(NULL, "Custom print called.", "FUNCTION!", NULL);
int nargs = lua_gettop(LUASTATE);
std::string string = "";
for (int i = 1; i <= nargs; i++)
{
if (i > 1) string += " ";
switch (lua_type(LUASTATE, i))
{
case LUA_TSTRING:
string += (std::string)lua_tostring(LUASTATE, i);
case LUA_TNUMBER:
string += (int)lua_tonumber(LUASTATE, i);
case LUA_TBOOLEAN:
string += (bool)lua_toboolean(LUASTATE, i);
}
}
std::cout << string << "\n";
return 0;
}
int pushs(lua_State* LuaState)
{
luaL_openlibs(LuaState);
lua_newtable(LuaState);
lua_pushcfunction(LuaState, print);
lua_setglobal(LuaState, "print");
lua_settop(LuaState, 0);
return 0;
}
int main()
{
lua_State* ls = luaL_newstate();
lua_State* LS = lua_newthread(ls);
pushs(LS);
while (true)
{
std::cout << " ";
std::string inputo;
std::cin >> inputo;
luaL_dostring(LS, inputo.c_str());
lua_settop(LS, 0);
}
lua_close(LS);
return 0;
}
Main problem
std::cin >> inputo does not read a full line from the standard input. It just reads a single word. So when you type the following input line in your shell:
print("Hello world")
Your main loop breaks it into two separate strings:
print("Hello
world")
And these string are evaluated independently by the Lua interpreter. None of these strings are valid Lua statements, so the interpreter doesn't execute them. lua_dostring will return an error code, and let an error message on the Lua stack.
To work line by line on the standard input, you can use std::getline, which works well in a loop:
std::string line;
while (std::getline(std::cin, line)) {
// do something with line.
}
Side notes
What follows is not directly related to your bug, but look suspicious:
std::string += int (or bool) interprets the int as a single char, and append this single character to the string.
Your switch/case seems to be missing break statements.
lua_State* ls is never closed.
I'm going through the process of learning c++, so I'm making a few programs/tools to do certain easy operations on the computer. In this example, I'm creating a program that will locate browsers on the computer (it will be used to clear browser cookies etc.). There is probably more advanced ways to do this more effieciently, but I'm trying to keep this as simple as possible at the moment.
So far, I'm trying to find out if the directory "C:\Program Files (x86)\Google\Chrome" exist. I get the address to the program files directory by using getenv ("Program Files (x86)", but how do I add the rest of the address after?
I can't use the + operator for concatenation, since the variable is const char * (bool PathIsDirectory() requires const char * as parameter).
std::cout << "Searching for browsers..." << std::endl;
const char *chromePath;
chromePath = getenv ("ProgramFiles(x86)");
bool result = PathIsDirectory(chromePath);
if(result == true)
{
std::cout << "-- Google Chrome - FOUND" << std::endl;
}
else
{
std::cout << "-- Google Chrome - NOT FOUND" << std::endl;
}
You can store the result of getenv() in a std::string object (as mentioned in
the comments). And then you can add the rest of the path using the + operator like this:
#include <string>
//...
std::string chromePath = getenv ("ProgramFiles(x86)");
chromePath += "\\remaining\\path";
bool result = PathIsDirectory(chromePath.c_str());
Note that you'll have to escape the backslashes as shown above.
I've been trying to learn a bit about socket programming in C++ and so have been developing a basic IRC bot. I've got it connecting and working, but I'm having an issue determining who has joined the channel (i.e. was the JOIN command for the bot itself, for a random user, or for me).
I'm using CLion on Windows 7.
I've got the following code:
//determine if message is JOIN command
if(regex_search(line, match, std::regex(R"(:([^!]*)!.*?JOIN)")))
{
//get the nickname of the bot (details.getNickName() shown in next code segment)
const char *trueNick = details.getNickName();
//reformat nickname because the following is returned from the method alone
//0x10042d0f9 <_ZStL6ignore+119> "CPlusPlusBotTest"
const char *nick = string(details.getNickName()).c_str();
//get the name of the user who joined
const char *name = match.str(1).c_str();
//debugging
std::cout << name << " - name\n";
std::cout << nick << " - nick\n";
//might not be the correct way to compare the two? but I'll sort that out later
if(name != nick)
{
//welcome the user
char param[1024];
sprintf(param, "%s :Hello, %s", details.getChannel(), name);
sendData("PRIVMSG", param);
}
}
I am unsure why I get the excess "stuff" (I have no idea what it is) from my getter, as it's simply a case of returning a private variable:
const char* BotDetails::getNickName() { return nickName; }
Regardless, that's not my issue given I can get rid of it (despite it possibly being rather hacky).
My issue is that when I connect to the channel for testing, and I set a breakpoint on the line assigning trueNick so I can see what happens as I step through the program, the following occurs:
1) trueNick is assigned the value: 0x10042d0f9 <_ZStL6ignore+119> "CPlusPlusBotTest"
2) nick is assigned the value: "CPlusPlusBotTest"
3) name is assigned the value: "Seanharrs" and nick is assigned the value: "Seanharrs"
This means when my debug statements run, nick and name are the same value. I am not sure why nick is being reassigned to be the same value as name, this should not occur. It happens every time as well, not just for my name. I tried using char arrays and strings instead but to no avail. I also find it strange that trueNick is never affected, it's only these two variables. Any help is appreciated (even if it's just an alt/better way to check this rather than a fix, because it may well be just an oddity on my end that nobody else experiences).
This line causes undefined behavior:
const char *nick = string(details.getNickName()).c_str();
It will construct a temporary string object and return a pointer to the data. However, being temporary means that it will be destructed immediately and the pointer will be invalid.
EDIT:
It turned out that OP misunderstood the additional information displayed by the debugger and interpreted it as the value of the variable. After clarifying that, there is no need for the "conversion" which causes undefined behavior and the code can just be:
const char *nick = details.getNickName();
const char *name = match.str(1).c_str();
if( strcmp(name, nick) == 0 )
{
//....
}
The example of undefined behavior is still shown below.
EXAMPLE CODE FOR THE UNDEFINED BEHAVIOR
Consider this code:
#include <iostream>
using namespace std;
int main() {
const char t[] = "0x10042d0f9 <_ZStL6ignore+119> \"CPlusPlusBotTest\"";
const char* pTrue = t;
const char* p = std::string(t).c_str();
std::cout << pTrue << std::endl;
std::cout << p << std::endl;
return 0;
}
it will output (rather: it may output):
0x10042d0f9 <_ZStL6ignore+119> "CPlusPlusBotTest"
0x10042d0f9 <_ZStL6ignore+119> "CPlusPlusBotTest"
(ideone.com used for this example and gave above output)
So from this you might think it was okay. (note however: I don't get the conversion mentioned by OP).
Now consider this code:
#include <iostream>
using namespace std;
int main() {
const char tdemo[] = "Some demo text"; // Added this line
const char t[] = "0x10042d0f9 <_ZStL6ignore+119> \"CPlusPlusBotTest\"";
const char* pTrue = t;
const char* p = std::string(t).c_str();
const char* pdemo = std::string(tdemo).c_str(); // Added this line
std::cout << pTrue << std::endl;
std::cout << p << std::endl;
return 0;
}
it will output (rather: it may output)
0x10042d0f9 <_ZStL6ignore+119> "CPlusPlusBotTest"
Some demo text
(ideone.com used for this example and gave above output)
As you can see the value of *p changed "unexpectedly". It changed because the pointer was invalid in the sense that it pointed to memory that was freed already. The extra line
const char* pdemo = std::string(tdemo).c_str();
caused the compiler to reuse that memory and consequently the value *p changed.
In other words - you have undefined behavior.
My guess is that your problem is inside details.getNickName();
It seems to me that the pointer returned is not pointing to the same test every time. Maybe it has some initialization problem so that it returns the wrong value the first time and then correct values afterwards.
The line causing undefined behavior can not do the conversion claimed by OP so it must be the return value from the function that changes.
I'm a bit confused. I'm trying to do some C++ and Python integration, but it's less than straightforward. I'm not using Boost, because I couldn't get Boost::Python to compile properly. But that's another story.
Currently, here's what I'm doing in C++:
//set everything up
PyObject* py_main_module = PyImport_AddModule("__main__");
PyObject* py_global_dict = PyModule_GetDict(py_main_module);
PyObject* py_local_dict = PyDict_New();
PyObject* py_return_value;
PyRun_SimpleString(data.c_str()); //runs Python code, which defines functions
//call a function defined by the python code
py_return_value = PyRun_String("test()", Py_single_input, py_global_dict, py_local_dict);
//attempt to check the type of the returned value
if(py_return_value != NULL) {
//this is the problem: all of these print 0
cout << PyList_Check(py_return_value) << endl;
cout << PySet_Check(py_return_value) << endl;
cout << PyFloat_Check(py_return_value) << endl;
} else {
cout << "IT WAS NULL?!" << endl;
}
The Python program (input to the C++ program as the string named "data"):
def test():
derp = 1.234
#derp = [1, 2, 3, 4]
#derp = set([1, 2, 3, 4])
return derp
Now, the problem is that the type checks aren't working. They all return 0, regardless of whether the Python function is returning a float, a list, or a set. What am I doing wrong?
Bonus points if anyone can tell me why the call to PyRun_String prints the returned value in the console. It's really annoying.
From the docs:
int Py_eval_input
The start symbol from the Python grammar for isolated expressions; for use with Py_CompileString().
int Py_file_input
The start symbol from the Python grammar for sequences of statements as read from a file or other source; for use with
Py_CompileString(). This is the symbol to use when compiling
arbitrarily long Python source code.
int Py_single_input
The start symbol from the Python grammar for a single statement; for use with Py_CompileString(). This is the symbol used for the
interactive interpreter loop.
Py_single_input evaluates the string as a statement. Statements don't inherently return anything, so you'll get None back from PyRun_String. Use Py_eval_input instead to evaluate the string as an expression and get a result.
Changing Py_single_input to Py_eval_input seems to resolve both issues.
The former treats the string as part of the interpreter loop, while the latter evaluates a single expression and gives you an object back. (I'm not sure what the return value means in the former case, but it's not the value of the expression.)
EDIT: Just tested it, and as per nneonneo's answer below, the result with Py_single_input is indeed Py_None.
I have a C++ program with many thousands of string literals in the code which need to be translated, for example:
statusBar->Print( "My Message" );
I wrapped the string literals with a function which looks up the value in a dictionary and returns the translated version:
statusBar->Print( Translated( "My Message" ) );
The problem is that after profiling I've discovered that doing this look up all over the code is a performance problem. What I'd like to do is change lines like that to:
static const char * translatedMessage5 = Translated( "My Message" );
statusBar->Print( translatedMessage5 );
But due to the many thousands of instances of this in the code, it's going to be error prone (and a bit of a maintenance nightmare). I was hoping that I could turn Translated into a macro which declared the static variable in-line. This obviously doesn't work. Anyone have a better idea?
I/O time needed to print your message should be several orders of magnitude more than any dictionary lookup time. If this is not the case, you are doing something wrong.
Tried and tested software is available that does what you need. I suggest you either study GNU Gettext, which is used by every other FOSS project out there, or just use it in your program instead of a homebrew solution.
EDIT: With C++0x it is possible to do what you want, but still consider using GNU Gettext as your real l10n engine. Here's some proof-of-concept little code:
#include <iostream>
const char* realTranslate(const char* txt)
{
std::cout << "*** translated " << txt << std::endl;
return txt; // use a real translation here such as gnu gettext
}
#define Translate(txt) \
(([]()->const char* \
{static const char* out = realTranslate(txt); return out;})())
int main ()
{
for (int i = 0; i < 10; ++i)
{
std::cout << Translate("This is a message") << std::endl;
std::cout << Translate("This is a message") << std::endl;
std::cout << Translate("This is another message") << std::endl;
}
}
I'm not sure what the real C++ standard is going to specify, but under gcc-4.6 the realTranslate() function is called 3 times.
Can you change to unique error codes and index them into vector? This simplifies the code and the lookup, and adding additional error messages becomes trivial. Also, ensures error messages added in this manner are more visible (externally to this application, for example -- could easily be published to a "User Guide" or similar).
#include <string>
#include <vector>
enum ErrorMessages
{
my_message,
my_other_message,
...
msg_high
};
std::vector<std::string> error_messages;
void init()
{
error_messages.resize(msg_high);
error_messages[my_msg] = "My Message";
error_messages[my_other_msg] = "My Other Message";
...
}
const char* const Translate(const ErrorMessage msg)
{
return error_messages[msg].c_str();
}
void f()
{
statusBar->Print(Translated(my_msg));
}
This might not help you here, but what you could do is declare a std::map that would hold a map of hash -> text pairs. The question here is if calculating hash code on a string will be same level of effort as translating it, and this I don't know.
char * Translate(char *source)
{
static std::map<int, char*> sources;
static std::map<int, char*> results;
int hashcode = CalculateHashCode(source);
std::map<int, char*>::const_iterator it = sources.find( source );
if ( it != sources.end() )
{
return results[ hashcode ];
}
... code to translate ...
results[ hashcode ] = translated;
}