While making a simple test case I met with another problem. Please help me.
Here are the files.
<<< bar.cpp >>>
#include <stdint.h>
#include <stdio.h>
extern "C" {
uint64_t var_from_lib;
}
class BC;
class BC {
public:
void bar(void);
BC();
~BC();
};
BC::BC()
{
}
BC::~BC()
{
}
void BC::bar(void)
{
printf("class function : var_from_lib = %lx\n", var_from_lib);
}
extern "C" {
void bar(void)
{
printf("global function : var_from_lib = %lx\n", var_from_lib);
BC tmp;
tmp.bar();
}
}
<<< main1.c >>>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
extern uint64_t var_from_lib; // = 0x12345678;
int main1(void)
{
void * dlh = dlopen("./libbar.so", RTLD_NOW);
if (!dlh) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
void (*bar)(void) = dlsym(dlh,"bar");
if (!bar) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
var_from_lib = 0x12341111;
bar();
return 0;
}
<<< main2.c >>>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
extern uint64_t var_from_lib; // = 0x12345678;
int main2(void)
{
void * dlh = dlopen("./libbar.so", RTLD_NOW);
if (!dlh) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
void (*bar)(void) = dlsym(dlh,"bar");
if (!bar) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
var_from_lib = 0x12342222;
bar();
return 0;
}
<<< main.c >>>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
extern uint64_t var_from_lib; // = 0x12345678;
uint64_t __attribute__((weak)) var_from_lib; // = 0x12345678;
extern int main1();
extern int main2();
int main(int argc, char *argv[])
{
if (atoi(argv[1]) == 1) {
main1();
}
else if (atoi(argv[1]) == 2) {
main2();
}
else {
printf("usage : main [1|2]\n");
}
return 0;
}
<<< Makefile >>>
.PHONY: all clean test
LDEXTRAFLAGS ?=
all: prog
%.o: %.c
gcc -c -Wall -fpic -o $# -ldl $<
%.o: %.cpp
g++ -c -Wall -fpic -o $# $<
libbar.so: bar.o
gcc -shared -o $# $<
main: main.o main1.o main2.o
gcc -c -Wall -o $# $< -rdynamic
prog: main.o main1.o main2.o | libbar.so
gcc $(LDEXTRAFLAGS) -o $# $^ -ldl
clean:
rm -f *.o *.so prog
Here is the execution result.
ckim#ckim-ubuntu:~/testdir$ make
gcc -c -Wall -fpic -o main.o -ldl main.c
gcc -c -Wall -fpic -o main1.o -ldl main1.c
gcc -c -Wall -fpic -o main2.o -ldl main2.c
g++ -c -Wall -fpic -o bar.o bar.cpp
gcc -shared -o libbar.so bar.o
gcc -o prog main.o main1.o main2.o -ldl
ckim#ckim-ubuntu:~/testdir$ prog 1
./libbar.so: undefined symbol: __gxx_personality_v0
How can I remove the error?
How can I remove the error?
Link your application with C++ library. Link with g++ or GLOBAL dlopen the libstdc++.so library. Overall, gcc -shared -o libbar.so bar.o should be g++ -shared -o libbar.so bar.o - it's a C++ library. gcc -Wl,--no-undefined -shared -o libbar.so bar.o catches the problem.
Related
How do I run a non-legacy PassManager? I have tried doing the following but there is some exception thrown when trying to invalidate the analysis manager in the run function. Is there something else I should do for initialization?
llvm::AnalysisManager<Module> mm;
PassBuilder builder;
auto pm = builder.buildModuleOptimizationPipeline(PassBuilder::OptimizationLevel::O3);
pm.run(module, mm );
These snippets illustrate how to run and setup to run modern custom function and module pass on some .c/.cpp file... complete with a makefile. This works for LLVM 6 which is pretty recent (march 2018). It does not use the legacy pass manager.
HelloWorld.cpp:
#include <llvm/Pass.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/raw_ostream.h>
namespace {
struct Hello : public llvm::FunctionPass {
static char ID;
Hello() : llvm::FunctionPass{ID} {}
bool runOnFunction(llvm::Function &F) override {
llvm::errs() << "Hello ";
llvm::errs().write_escaped(F.getName()) << "\n";
return false;
}
};
struct Hello2 : public llvm::ModulePass {
static char ID;
Hello2() : llvm::ModulePass{ID} {}
bool runOnModule(llvm::Module &M) override {
llvm::errs() << "Name of the module ", llvm::errs().write_escaped(M.getName()) << "\n";
for(auto iter = M.getFunctionList().begin(); iter != M.getFunctionList().end(); ++iter) {
llvm::errs() << "Function name:" << iter->getName() << "\n";
}
return false;
}
};
}
char Hello::ID = 0;
static llvm::RegisterPass<Hello> X("Hello",
"Hello World Pass",
false,
false
);
char Hello2::ID = 1;
static llvm::RegisterPass<Hello2> Y("Hello2",
"Hello World2 pass",
false,
false
);
Corresponding makefile:
LLVM_VERSION=
LLVM_INCLUDEDIR = `llvm-config-6.0 --includedir`
LLVM_FLAGS = `llvm-config-6.0 --cxxflags --ldflags --system-libs --libs all`
CXX = clang++-6.0
CXXFLAGS = -g -std=c++11 -O3 -I $(LLVM_INCLUDEDIR) -I $(LLVM_INCLUDEDIR)
Hello.so:
$(CXX) -fPIC $(CXXFLAGS) HelloWorld.cpp $(LLVM_FLAGS) -shared -o Hello.so
Hello: Hello.so
testfile:
clang++-6.0 -emit-llvm -c test.cpp -o test.bc
runFunctionPassOnTestFile: Hello testfile
opt-6.0 -load ./Hello.so -Hello < test.bc > /dev/null
runModulePassOnTestfile: Hello testfile
opt-6.0 -load ./Hello.so -Hello2 < test.bc > /dev/null
clean:
rm *.o *.so *.out *~
DBG:
#echo LLVM INCLUDE DIRS $(LLVM_INCLUDEDIR) $(test)
A simple file to test everything on, test.cpp:
#include <stdio.h>
#include <stdlib.h>
int a = 4;
int c = 5;
int d = 6;
int e = 7;
int bar() { int *a = (int*) malloc(4); e = 1; return 1;}
int foo() { return 2; }
int barfoo() { return 3; }
int main() {
printf("Testing testing\n");
return 0;
}
I figured that the problem was that I was not using ./a.out instead of ./filename, but that wasn't the case.
This is how I compile my program:
g++ -o -Wall -pthread filename.cpp
Running:
./filename
I figured that running pthread programs would be different than running a standard c++ program, but that wasn't the case.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct argStruct {
int arg1;
int arg2;
};
void *sum(void *arguments) {
struct argStruct *args = (struct argStruct *)arguments;
int a = args -> arg1;
int b = args -> arg2;
int c = a + b;
printf("%d + %d = %d ",a,b,c);
pthread_exit(NULL);
}
int main() {
pthread_t thr1, thr2;
struct argStruct args;
args.arg1 = 3;
args.arg2 = 10;
int t1, t2;
pthread_create(&thr1, NULL, &sum, (void *)&args);
pthread_create(&thr2, NULL, &sum, (void *)&args);
pthread_join(thr1, NULL);
pthread_join(thr2, NULL);
exit(EXIT_SUCCESS);
}
By calling
g++ -o -Wall -pthread filename.cpp
You instruct the compiler to write the result to a file named -Wall.
You therefore want to use one of these
g++ -Wall -pthread filename.cpp
g++ -Wall -pthread -o filename filename.cpp
The first writes the result to a.out, the second to filename. (Also it enables the warnings)
This is a follow-up question to this one.
I fixed double free and memory corruption by adding copy constructor and assignment constructor to class File and Buffer. But that remote server reports there is segmentation fault. Is there any way to cause class File or Buffer segment fault? I think segment fault is normally related to stack. But I don't have stack operation in these 2 classes.
Buffer.h
#ifndef __BUFFER_H__
#define __BUFFER_H__
#include <stdlib.h>
#include <cerrno>
#include <stdio.h>
class Buffer
{
private:
char * buffer;
int size;
Buffer(const Buffer &);
Buffer& operator=(const Buffer &);
public:
Buffer(int size);
~Buffer();
void reverse(int size);
friend class File;
};
#endif
Buffer.cc:
#include "Buffer.h"
#include "Exception.h"
Buffer::Buffer(int size)
{
this -> size = size;
this -> buffer = (char *)malloc(size);
if(this -> buffer == NULL)
throw Exception(errno);
}
Buffer::~Buffer()
{
// // if(this -> buffer != NULL)
// {
free(this -> buffer);
// this -> buffer = NULL;
// }
}
void Buffer::reverse(int size)
{
char tmp;
int i;
char * tmpb = this -> buffer;
for(i = 0; i < size / 2; i++)
{
tmp = tmpb[i];
tmpb[i] = tmpb[size - i - 1];
// printf("exchange %x with %x\n", tmp & 0xff, tmpb[i] & 0xff);
tmpb[size - i - 1] = tmp;
}
}
File.h:
#ifndef __FILE_H__
#define __FILE_H__
#include "Buffer.h"
#include "Exception.h"
#include <stdio.h>
#include <cerrno>
class File
{
private:
FILE * f;
File(const Buffer &);
File& operator=(const File &);
public:
int whence;
// Note: opening the same file twice for writing ("w")
// at the same time is forbidden
File(const char* name, const char *mode);
~File();
int read(Buffer& buffer, int size);
void write(Buffer& buffer, int size);
void seek(int pos);
void close();
// void seek(long offset, int whence);
long size();
};
#endif
File.cc:
#include "File.h"
File::File(const char* name, const char *mode)
{
f = fopen(name, mode);
if(f == NULL)
throw Exception(errno);
}
File::~File()
{
if(f != NULL)
fclose(f);
}
int File::read(Buffer& buffer, int size)
{
clearerr(this -> f);
size_t tmp;
tmp = fread(buffer.buffer, 1, size, this -> f);
// printf("%ld bytes read\n", tmp);
// for(int i = 0; i < tmp; i++)
// printf("%x ", buffer.buffer[i] & 0xff);
// printf("\n");
if(feof(this -> f) != 0)
return EOF;
if(ferror(this -> f) != 0)
throw Exception(errno);
return tmp;
}
void File::write(Buffer& buffer, int size)
{
size_t tmp;
clearerr(this -> f);
tmp = fwrite(buffer.buffer, 1, size, this -> f);
// printf("%ld bytes written\n", tmp);
// for(int i = 0; i < tmp; i++)
// printf("%x ", buffer.buffer[i] & 0xff);
// printf("\n");
if(ferror(this -> f) != 0)
throw Exception(errno);
}
void File::seek(int pos)
{
int ret = fseek(this -> f, pos, this -> whence);
if(ret != 0)
throw Exception(errno);
}
void File::close()
{
int tmp;
if(this -> f != NULL)
tmp = fclose(this -> f);
this -> f = NULL;
if(tmp != 0)
throw Exception(errno);
}
long File::size()
{
if(fseek(this -> f, 0, SEEK_END) != 0)
throw Exception(errno);
long tmp = ftell(this -> f);
if(tmp == -1)
throw Exception(errno);
if(fseek(this -> f, 0, SEEK_SET) != 0)
throw Exception(errno);
return tmp;
}
NOTE: I have to use C style code. Otherwise I would fail the server test. That is a hard requirement. Well, you may think this requirement is silly. But this is the requirement. Maybe one point is learning the bad while someone mixing C and C++.
The server provides a main function to test my implementation. Just compile using make. The result is a program named rcopy which reverses content of a file byte by byte and then outputs to a new file.
Here is the detailed error output:
make: Entering directory `/home/vmcheck/testhome/co/rcopy'
g++ -c rcopy.cc
g++ -c Buffer.cc
g++ -c Exception.cc
g++ -c File.cc
g++ rcopy.o Buffer.o Exception.o File.o -o rcopy
make: Leaving directory `/home/vmcheck/testhome/co/rcopy'
======== COMPILING AGAINST OUR TESTS ========
g++ -c -Wall -I./ t1.cc -ot1.o
g++ -ot1 t1.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ t2.cc -ot2.o
g++ -ot2 t2.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ t3.cc -ot3.o
g++ -ot3 t3.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ t4.cc -ot4.o
g++ -ot4 t4.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ t5.cc -ot5.o
g++ -ot5 t5.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ t6.cc -ot6.o
g++ -ot6 t6.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ t7.cc -ot7.o
g++ -ot7 t7.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ f1.cc -of1.o
gcc failed_read.c -ldl -shared -fPIC -o failed_read.so
gcc failed_write.c -ldl -shared -fPIC -o failed_write.so
failed_write.c:5:7: warning: conflicting types for built-in function ‘fwrite’ [enabled by default]
g++ -of1 f1.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ f2.cc -of2.o
g++ -of2 f2.o Buffer.o Exception.o File.o
========= TESTING RCOPY ==========
Run: large file
size of input file: 16473
Run: small file
size of input file: 0
========= TESTING EXCEPTION BEHAVIOUR ==========
*** Test 1 ***
*** Test 2 ***
*** Test 3 ***
bash: line 1: 22041 Segmentation fault ./t3
FAILED
The bash script isn't source of the segment fault. I can confirm this. Noted that the test serve could provide many various versions of buggy main to test File, Buffer and Exception.
A possible source of crash are the read and write methods, when called with invalid parameters. For instance, read can be called with a buffer having a size 10, but the function read is requested to read 20 bytes. In this case, you will overflow your buffer.
You have two solutions: either you change your buffer class to be able to resize dinamically, either you read/write up to the maximal size of the buffer, for instance:
tmp = fread(buffer.buffer, 1, min(size, buffer.size), this -> f);
It goes the same for the write.
The following program illustrates the issue:
Makefile:
CFLAGS = -O3 -std=c++0x
LDFLAGS = -lreadline
test: test.o
g++ $(CFLAGS) $< $(LDFLAGS) -o $#
test.o: test.cpp Makefile
g++ $(CFLAGS) -c $<
test.cpp:
#include <fnmatch.h>
#include <readline/readline.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
static double time()
{
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return ts.tv_sec + (1e-9 * (double)ts.tv_nsec);
}
static void time_fnmatch()
{
for (int i = 0; i < 2; i++)
{
double t = time();
for (int i = 0; i < 1000000; i++)
{
fnmatch("*.o", "testfile", FNM_PERIOD);
}
fprintf(stderr, "%f\n", time()-t);
}
}
int main()
{
time_fnmatch();
char *input = readline("> ");
free(input);
time_fnmatch();
}
Output:
0.045371
0.044537
>
0.185246
0.181607
Before calling readline(), the fnmatch calls are about 4x faster. Although
this performance difference is worrying, I'm most interested in finding out
what exactly the readline() call might be doing to the program state that
would have this effect on other library calls.
Just a guess: readline initialization probably calls setlocale.
When a program starts up, it is in the C locale; a call to setlocale(LC_ALL, "") will enable the default locale, and these days, the default locale usually uses UTF-8, in which case many string operations become more complex. (Even just iterating over a string.)
I face a error of "multiple definition of "
I got 3 files, namely currency.h, currency.cpp,main.cpp
At currencyConverter.h under currencyConverter class
I did
using namespace std;
class currencyConverter
{
string result;
stringstream ss;
size_t found,found2;
public:
void getInbetween(string,string);
};
#endif /* CURRENCYCONVERTER_H */
Then at currencyConverter.cpp I did
#include "currencyConverter.h"
void currencyConverter::getInbetween(string selection,string str2,string str3,string sdata)
{
buffer[result.length()] = '\0'; //insert '\0'
char * pch;
pch = strtok (buffer," ");
}
void currencyConverter::webparser(const string siteurl,const string filename)
{
ss << "lynx -dump '" << siteurl << "' > " << filename;
}
string currencyConverter::userOption()
{
//some code
return selection;
}
at main2.cpp
#include<iostream>
#include"currencyConverter.cpp"
using namespace std;
int main() {
currencyConverter c;
string exitstr;
if(selection!="6")
{
c.webparser(parsePage,"file.txt");
//now perform searchstring
c.searchString(selection,"file.txt");
}
}while (1);
return 0;
}
This is my make file
# ExampleTests Project
SRCS = main2.cpp
HDRS =
PROJ = main
CC = g++
OBJS = $(SRCS:.cpp=.o)
APP = $(PROJ).exe
CFLAGS = -c -g -Wall -I/opt/local/include
ifeq (,$(findstring CYGWIN,$(shell uname)))
LIBS = -lcppunit -ldl
all: $(APP)
$(APP): $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) -o $(APP) $(LIBS)
clean:
rm -f *.o $(APP)
But i receive this error on compiler
How to get this fix.. I did not use it twice. I pasted part of my currencyConverter.cpp with the function webparser, is there a error in the way i call my function at main2.cpp ?
rm -f *.o main.exe
CLEAN SUCCESSFUL (total time: 86ms)
g++ -c -o main2.o main2.cpp
td::char_traits, std::allocator >)':
currencyConverter.cpp:(.text+0xcec): multiple definition of `currencyConverter::webparser(std::basic_string, std::allocator >, std::basic_string, std::allocator >)'
main2.o:main2.cpp:(.text+0xcec): first defined here
collect2: ld returned 1 exit status
make: * [main.exe] Error 1
Include a header file, not a cpp:
#include"currencyConverter.cpp"
should be
#include"currencyConverter.h"
in your main2.cpp