C palindrome program - undefined reference to main - c

I wrote an function, which checks, if string of char is palindrome or not.
//pan.c
#include <stdbool.h>
#include "funs.h"
#include <stdio.h>
#include <string.h>
bool palindrom(char napis[])
{
int begin, middle, end, length = 0;
while(napis[length] != '\0')
length++;
end = length - 1;
middle = length;
for (begin = 0; begin < middle; begin++)
{
if(napis[begin] != napis[end])
{
return false;
break;
}
end--;
}
if(begin == middle)
return true;
}
I also created funs.h
//funs.h
#include <stdbool.h>
bool palindrom();
Now, I'm trying to use this function in my main function
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "funs.h"
int main()
{
char text[100];
bool result;
printf("Enter an char: ");
scanf("%s", text);
result = palindrom(text);
if(result)
{
printf("Brawo!\n");
}
else
{
printf("Gówno!\n");
}
return 0;
}
I also created makefile:
# Makefile
all: main
main: main.o pan.o
clang -o main main.o pan.o
main.o: main.c
clang -c main.c
pan.o: pan.c
clang -c pan.c
clean:
rm -f main *.o *~
Everything seems fine and works in single file, but when I try to compile them separately they "don't see" each other. Makefile also seems to work badly, but I can't see any mistakes. Can you help me fix it?

When I try "make" command it returns "makefile:15: *** missing separator. Stop." comment and do nothing.
Did you actually look at line 15 of your makefile? Notice that it's flush against the margin instead of indented by a tab character.
When I'm compiling pan.c with "clang pan.c -Wall --pedantic -std=c11 -o pan" command: 1 warning generated. /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-l‌​inux-gnu/crt1.o: In function _start': (.text+0x20): undefined reference to main'
Indeed, your pan.c does not have a main() function. So don't try to compile it by itself. How about
clang main.c pan.c -Wall --pedantic -std=c11 -o pan

Related

Compile and run a C file from another C program without using command line

I have two C programs:
Main.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
system("gcc x.c -o x");
system("x.exe");
return 0;
}
x.c
#include <stdio.h>
int main() {
printf("hello world!");
return 0;
}
From Main.c I need to compile and run x.c without using the command line. I've tried this but the code didn't work.
Thanks
This function call will compile your file and run it in one line :
system("gcc x.c -o x && x.exe");

C strchr works with NULL value on HPUX but segfaults on RHEL

I'm moving some code from HPUX 11.11 to RHEL 7.5 and it includes a function that uses strchr. On HPUX it runs fine, and on RHEL there is a segmentation fault. I isolated the code and created the following simple test, with the subsequent results. It looks like HPUX strchr is returning an empty string rather than NULL when the character is not found. This is not what the man page says. I have found it might not be the strchr function but the difference in how HPUX handles NULL values, or a difference in compiler from cc to gcc. Does anyone actually know what's happening here? Why is the code not segfaulting on HPUX?
C Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
int i = 0;
char* phrase = "Here is my phrase.";
while (i < 5){
phrase = strchr(phrase, ' ');
++phrase;
++i;
}
return 0;
}
HPUX makefile:
BIN=/path/to/bin/
CFLAGS=-c
#----------Targets----------#
default: $(BIN)strchrtest
#----------Objects----------#
OBJS = strchrtest.o
#----------------BUILD----------------#
$(BIN)strchrtest: $(OBJS)
cc -o $# $(OBJS)
strchrtest.o: strchrtest.c
cc $(CFLAGS) strchrtest.c
RHEL makefile:
CC=gcc
BIN=/path/to/bin/
CFLAGS=-c -g -Wall
#----------Targets----------#
default: $(BIN)strchrtest
#----------Objects----------#
OBJS = strchrtest.o
#----------------BUILD----------------#
$(BIN)strchrtest: $(OBJS)
$(CC) -o $# $(OBJS)
strchrtest.o: strchrtest.c
$(CC) $(CFLAGS) strchrtest.c
HPUX is just a successful result. No segmentation fault.
RHEL results:
(gdb) run
Starting program: ../strchrtest
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b4c5f4 in __strchr_sse42 () from /lib64/libc.so.6
Copied form my comment below: The point is that the strchr function itself is causing the segfault when asked to find a character in the null pointer (that has been incremented), but on HPUX it doesn't. So it's either returning an empty string that is then passed strchr on the next loop, or strchr is handling the null pointer parameter differently by not segfaulting. Or I misunderstand what's happening.
Make two files, r.c, main.c as such
r.c:
int *r = 0;
main.c:
extern int *r;
int main(void) {
return *r;
}
then cc main.c r.c; ./a.out
if it doesn't sigsegv, your runtime is mapping a page of nulls for you.
you could do it yourself - main.c:
#include <sys/mman.h>
int main(void) {
p = mmap(0, 1, PROT_READ, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
if (p == MAP_FAILED) {
perror("mmap");
exit(1);
}
....
}
but at least on ubuntu, you need to be root :(

backtrace function only got the last frame

I want to call backtrace function to get the callchain, the following is my code, this code works good on x86, but can't work on mips
gcc -o hello-x86 hello.c -g -rdynamic -O0 -Wall
./hello-x86
size = 6
0x40095c : ./hello-x86(foo+0x1f) [0x40095c]
0x400a2d : ./hello-x86(b+0x9) [0x400a2d]
0x400a38 : ./hello-x86(a+0x9) [0x400a38]
0x400a4e : ./hello-x86(main+0x14) [0x400a4e]
0x7fee0d003f45 : /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7fee0d003f45]
0x400879 : ./hello-x86() [0x400879]
but on mips, just only got the last frame, how to fix it ?
mips-linux-gnu-gcc -o hello hello.c -g -rdynamic -O0 -Wall -msoft-float -EL
./hello
size = 1
0x400a04 : ./hello(foo+0x24) [0x400a04]
can't get b and a and main. but i can got full callchain in gdb, why can't got it via backtrace function ?
my toolchain is codesourcery mips-2016.05, the libc version is 2.23
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <execinfo.h>
#define BACKTRACE_SIZ 100
int i = 0;
void foo(void)
{
void *array[BACKTRACE_SIZ];
size_t size, i;
char **strings;
size = backtrace(array, BACKTRACE_SIZ);
strings = backtrace_symbols(array, size);
printf("size = %ld\n", (long)size);
for (i = 0; i < size; ++i) {
printf("%p : %s\n", array[i], strings[i]);
}
free(strings);
while (1) {
i++;
}
}
void b(void)
{
foo();
}
void a(void)
{
b();
}
int main(int argc, char **argv)
{
a();
return 0;
}
i tried -fno-omit-frame-pointer and -fomit-frame-pointer, these two option all can't work.
mips-linux-gnu-gcc -o hello hello.c -g -rdynamic -O0 -Wall -msoft-float -EL -fomit-frame-pointer
mips-linux-gnu-gcc -o hello hello.c -g -rdynamic -O0 -Wall -msoft-float -EL -fno-omit-frame-pointer
and i tried on my arm board, it worse, the size is 0 on arm

I redefine a standard C library function in a dynamic library, but I can't use it

There is a simple example to describe my problem:
I have 3 files, main, level1.so and level2.so. (My OS is solaris11.3, gcc version is 3.4.3)
In main, it calls execute() from level1.so. And the execute() calls run() from level2.so. And the run() calls fcloseall() which is redefined in level2.so.
fcloseall() is redefined to do nothing (it will close all opened fds include stdout, stdin and stderr originally).
Now I want print something around execute() in main, but only the message before execute() is printed.
The codes are shown below:
The level2.so is compiled from level2.c and level2depend.c.
level2.c:
#include <stdio.h>
int run()
{
fcloseall();
return 0;
}
level2depend.c:
#include <stdio.h>
int fcloseall() //redefine the std c function fcloseall
{
printf("in redefined fcloseall\n");
return 0;
}
The level1.so is compiled from level1.c.
level1.c
#include <dlfcn.h>
int execute()
{
int (*sofunc)(void);
void * lib_handle = NULL;
char *errorInfo;
lib_handle = dlopen("./liblevel2.so",RTLD_LAZY);
if(!lib_handle)
{
return 0;
}
sofunc = (int(*)(void))dlsym(lib_handle,"run");
errorInfo = dlerror();
if (errorInfo != NULL){
dlclose(lib_handle);
return 0;
}
int ret = sofunc();
dlclose(lib_handle);
return 0;
}
The main is compiled from main.c.
main.c
#include <dlfcn.h>
#include <stdio.h>
int main()
{
int (*sofunc)(void);
void * lib_handle = NULL;
char *errorInfo;
lib_handle = dlopen("./liblevel1.so",RTLD_LAZY);
if(!lib_handle)
{
return 0;
}
sofunc = (int(*)(void))dlsym(lib_handle,"execute");
errorInfo = dlerror();
if (errorInfo != NULL){
dlclose(lib_handle);
return 0;
}
printf("before\n");
int ret = sofunc();
printf("after\n");
dlclose(lib_handle);
return 0;
}
The makefile is:
all:
gcc level2depend.c -o level2depend.o -c -g -fPIC
gcc level2.c -o level2.o -c -g -fPIC
gcc -shared -g level2.o level2depend.o -o liblevel2.so -fPIC
gcc level1.c -o level1.o -c -g -fPIC
gcc level1.o -o liblevel1.so -shared -fPIC
gcc main.c -o main -g -ldl
clean:
rm level2depend.o level1.o liblevel1.so level2.o liblevel2.so main
I execute main and the result is:
root#solaris#./main
before
If I change the makefile as gcc main.c -o main -g -ldl -llevel2, the result is:
root#solaris#./main
before
in redefined fcloseall
after
And this is what I want.
I want know why this happen. Thanks!
You can use the wrap function provided by ld.
gcc -Wl,-wrap,fcloseall ....
and in your source code,
int __wrap_fcloseall(void)
{...}

Difference between getting function pointers from shared library

The question is how I can get function address from shared library (UNIX/LINUX)?
I had written some testcases in C (see below), compiled and run on Ubuntu 10.04 (amd64) and FreeBSD-8.2 (amd64). I hadn't feel any difference but I want to know more about possible troubles.
Here they are:
Test 1
lib.c
char* f0(void) {
return "Hello, World!";
}
main.c
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
void *hlib, *addr;
char* (*foo)(void);
char* s;
int main(int argc, char** argv) {
if ( !(hlib = dlopen("./lib.so", RTLD_LAZY)) )
return 1;
if ( !(addr = foo = dlsym(hlib, "f0")) )
return 2;
s = foo();
printf("%p => %s\n", addr, s);
return 0;
}
Now build it:
gcc -o lib.o -c lib.c -Wall -Werror -O3 -fPIC
gcc -o lib.so -shared -nostartfiles lib.o
gcc -o main.o -c main.c -Wall -Werror -O3
gcc -o prog main.o -ldl
This prints the address of library function f0() and the result of execution.
Test 2
lib.h (define here the standard interface of dynamically linking libraries)
#ifndef __LIB_H__
#define __LIB_H__
typedef struct __syminfo {
char* name; // function name
void* addr; // function address
} syminfo_t;
typedef struct __libinfo {
int num; // number of exported functions
syminfo_t sym[1]; // vector of exported function information
} libinfo_t;
extern int (*__getinfo)(libinfo_t**);
#endif
/* __LIB_H__
*/
lib.c (the library itself)
#include <stdlib.h>
#include <lib.h>
static libinfo_t* li;
char* foo(void);
__attribute__((constructor)) void __init() {
if ( (li = calloc(1, sizeof(libinfo_t))) ) {
li->num = 1;
li->sym[0].name = "foo";
li->sym[0].addr = &foo;
}
}
__attribute__((destructor)) void __free() {
if (li)
free(li);
}
int getinfo(libinfo_t** inf) {
if (!inf)
return -1;
*inf = li;
return 0;
}
char* foo(void) {
return "Hello, World!";
}
main.c
#include <stdio.h>
#include <dlfcn.h>
#include <lib.h>
libinfo_t* inf;
void* hlib;
int (*__getinfo)(libinfo_t**);
char* (*foo)(void);
char* s;
int main(int argc, char** argv) {
if ( !(hlib = dlopen("./lib.so", RTLD_LAZY)) )
return 1;
if ( !(__getinfo = dlsym(hlib, "getinfo")) )
return 2;
if (__getinfo(&inf))
return 3;
if ( !(foo = inf->sym[0].addr) )
return 4;
s = foo();
printf("%p => %s\n", inf->sym[0].addr, s);
return 0;
}
Now compile it (without -nostartfiles):
gcc -I. -o lib.o -c lib.c -Wall -Werror -O3 -fPIC
gcc -o lib.so lib.o -shared
gcc -I. -o main.o -c main.c -Wall -Werror -O3
gcc -o prog main.o -ldl
This printf the same as Test 1: the address of library function foo() and the result of its execution.
I tried to show how can I get shared library function address, but am I right in the second test? Shall I have got some troubles with it?
NOTE: in FreeBSD-8.2 there is no need to use -ldl argument, all dlfcn.h routines are in libc library.
Respectively waithing for any explanations.
That looks fairly standard to me. The only thing that you're using that could pose some problems is that you're using gcc attributes to create a constructor and destructor for your shared library. That may not be entirely portable; it depends on what platforms you care about.
Note that in this specific case there's no need to do something this complicated. The information that you're returning from the shared library in your second example is all known at compile time, so you can just create a static struct with that information and either retrieve the address of the struct with dlsym and poke around in it from the main program or call a known function to return the struct. (The latter is slightly more flexible in some corner cases, but both are fairly flexible.)

Resources