What does -fPIC Mean when compiling a shared library - c
I am trying to create a shared library in linux I get the following error when trying to compile this :
relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
If i remove the contents of GetCrc16 it Works. What am I doing wrong ?
/*
* main.c
*
* Created on: Jul 3, 2012
* Author: opc0de
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <resolv.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <mysql/mysql.h>
#include <arpa/inet.h>
#include <curl/curl.h>
typedef struct param
{
int * csock;
char * IMEI;
}param;
#define DAEMON_NAME "MEGA_TRACKER"
static const unsigned short crctab16[] =
{
0X0000, 0X1189, 0X2312, 0X329B, 0X4624, 0X57AD, 0X6536, 0X74BF,
0X8C48, 0X9DC1, 0XAF5A, 0XBED3, 0XCA6C, 0XDBE5, 0XE97E, 0XF8F7,
0X1081, 0X0108, 0X3393, 0X221A, 0X56A5, 0X472C, 0X75B7, 0X643E,
0X9CC9, 0X8D40, 0XBFDB, 0XAE52, 0XDAED, 0XCB64, 0XF9FF, 0XE876,
0X2102, 0X308B, 0X0210, 0X1399, 0X6726, 0X76AF, 0X4434, 0X55BD,
0XAD4A, 0XBCC3, 0X8E58, 0X9FD1, 0XEB6E, 0XFAE7, 0XC87C, 0XD9F5,
0X3183, 0X200A, 0X1291, 0X0318, 0X77A7, 0X662E, 0X54B5, 0X453C,
0XBDCB, 0XAC42, 0X9ED9, 0X8F50, 0XFBEF, 0XEA66, 0XD8FD, 0XC974,
0X4204, 0X538D, 0X6116, 0X709F, 0X0420, 0X15A9, 0X2732, 0X36BB,
0XCE4C, 0XDFC5, 0XED5E, 0XFCD7, 0X8868, 0X99E1, 0XAB7A, 0XBAF3,
0X5285, 0X430C, 0X7197, 0X601E, 0X14A1, 0X0528, 0X37B3, 0X263A,
0XDECD, 0XCF44, 0XFDDF, 0XEC56, 0X98E9, 0X8960, 0XBBFB, 0XAA72,
0X6306, 0X728F, 0X4014, 0X519D, 0X2522, 0X34AB, 0X0630, 0X17B9,
0XEF4E, 0XFEC7, 0XCC5C, 0XDDD5, 0XA96A, 0XB8E3, 0X8A78, 0X9BF1,
0X7387, 0X620E, 0X5095, 0X411C, 0X35A3, 0X242A, 0X16B1, 0X0738,
0XFFCF, 0XEE46, 0XDCDD, 0XCD54, 0XB9EB, 0XA862, 0X9AF9, 0X8B70,
0X8408, 0X9581, 0XA71A, 0XB693, 0XC22C, 0XD3A5, 0XE13E, 0XF0B7,
0X0840, 0X19C9, 0X2B52, 0X3ADB, 0X4E64, 0X5FED, 0X6D76, 0X7CFF,
0X9489, 0X8500, 0XB79B, 0XA612, 0XD2AD, 0XC324, 0XF1BF, 0XE036,
0X18C1, 0X0948, 0X3BD3, 0X2A5A, 0X5EE5, 0X4F6C, 0X7DF7, 0X6C7E,
0XA50A, 0XB483, 0X8618, 0X9791, 0XE32E, 0XF2A7, 0XC03C, 0XD1B5,
0X2942, 0X38CB, 0X0A50, 0X1BD9, 0X6F66, 0X7EEF, 0X4C74, 0X5DFD,
0XB58B, 0XA402, 0X9699, 0X8710, 0XF3AF, 0XE226, 0XD0BD, 0XC134,
0X39C3, 0X284A, 0X1AD1, 0X0B58, 0X7FE7, 0X6E6E, 0X5CF5, 0X4D7C,
0XC60C, 0XD785, 0XE51E, 0XF497, 0X8028, 0X91A1, 0XA33A, 0XB2B3,
0X4A44, 0X5BCD, 0X6956, 0X78DF, 0X0C60, 0X1DE9, 0X2F72, 0X3EFB,
0XD68D, 0XC704, 0XF59F, 0XE416, 0X90A9, 0X8120, 0XB3BB, 0XA232,
0X5AC5, 0X4B4C, 0X79D7, 0X685E, 0X1CE1, 0X0D68, 0X3FF3, 0X2E7A,
0XE70E, 0XF687, 0XC41C, 0XD595, 0XA12A, 0XB0A3, 0X8238, 0X93B1,
0X6B46, 0X7ACF, 0X4854, 0X59DD, 0X2D62, 0X3CEB, 0X0E70, 0X1FF9,
0XF78F, 0XE606, 0XD49D, 0XC514, 0XB1AB, 0XA022, 0X92B9, 0X8330,
0X7BC7, 0X6A4E, 0X58D5, 0X495C, 0X3DE3, 0X2C6A, 0X1EF1, 0X0F78,
};
unsigned char response[] = { 0x78, 0x78, 0x05 , 0x00 ,0x00, 0x00, 0x00, 0x00,0x0D, 0x0A};
char Hexars[] = {'0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'a', 'b','c', 'd', 'e', 'f' };
unsigned short GetCrc16(const unsigned char* pData, int nLength)
{
unsigned short fcs = 0xffff; // initialize
while(nLength>0){
fcs = (fcs >> 8) ^ crctab16[(fcs ^ *pData) & 0xff];
nLength--;
pData++;
}
return ~fcs;
}
-fPIC instructs the compiler to compile your code as Position Independent Code. This is needed so that the machine code executed properly regardless of the absolute address.
These are needed mainly for shared libraries, as the same library code can be loaded in a location in each program's address space where it will not overlap with other uses of memory etc.
Following links can provide more info.
Wikipedia: http://en.wikipedia.org/wiki/Position_independent_code
SO: Why isn't all code compiled position independent?
The command line option -fPIC means make position independent code. This is needed when compiling shared objects (.so) for 64bit. You were able to get away without using it on 32bit; even though it was recommended.
Related
How do I reimplement realloc in assembly on mac os x?
I don't need any of this, it's for fun I implemented realloc on linux before using map and mremap. I ran dtruss on the below code and I see two write calls, nothing in between. Using bash and time b.c is significantly slower than a.c which leaves me to believe realloc doesn't use a memcpy (and likely changes virtual pages). If I wanted to implement my own C library or write a realloc in assembly how would I implement it to get as good performance as a.c? % cat a.c b.c #include <stdlib.h> #include <unistd.h> #include <string.h> int main() { write(1, "Hel", 3); void*p1=malloc(1024*1024*512); memset(p1, '1', 1024*1024*512); malloc(4096); void*p =realloc(p1, 1024*1024*1024); memset(p+1024*1024*512, '0', 1024*1024*512); write(1, "lo\n", 3); } #include <stdlib.h> #include <unistd.h> #include <string.h> int main() { write(1, "Hel", 3); void*p1=malloc(1024*1024*512); memset(p1, '1', 1024*1024*512); void*p =malloc(1024*1024*1024); memcpy(p, p1, 1024*1024*512); memset(p+1024*1024*512, '0', 1024*1024*512); write(1, "lo\n", 3); }
'SO_USELOOPBACK' was not declared in this scope
I am checking socket options and I got this error when I compile. I tried to google it and it looks like no one has encountered this problem before. #include <netinet/tcp.h> #include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <netinet/in.h> #include <netdb.h> #include <stdlib.h> static char *sock_str_flag(union val *, int); struct sock_opts { const char *opt_str; int opt_level; int opt_name; char *(*opt_val_str)(union val *, int); }sock_opts[] = { { "SO_USELOOPBACK", SOL_SOCKET, SO_USELOOPBACK, sock_str_flag } //this is the error };
The socket option SO_USELOOPBACK is not a POSIX standard. The man page setsockopt() describes the nature of SO_USELOOPBACK in detail. The SO_USELOOPBACK is a [Digital] standard. Text paragraphs preceded by [Digital] document features that are included in the DIGITAL UNIX software but are not currently specified by any standard that applies to the interface being described. Use these features when source code portability across multiple UNIX platforms is less important than the capabilities that the features provide. For portability, you need to have ifdef checks. struct sock_opts { const char *opt_str; int opt_level; int opt_name; char *(*opt_val_str)(union val *, int); }sock_opts[] = { /* .... */ #ifdef SO_USELOOPBACK {"SO_USELOOPBACK", SOL_SOCKET, SO_USELOOPBACK, sock_str_flag } #endif /* .... */ };
Header file for SDL_Overlay
I plan to use both SDL_GetKeyboardState and SDL_Overlay but it seems there is a conflict. #include <stdio.h> #include <SDL/SDL.h> #include <SDL2/SDL.h> int main() { const Uint8 *keystate = SDL_GetKeyboardState(NULL); SDL_Overlay *bmp; printf("hello world!"); } Compile: gcc -c main.cpp When order of headers are: #include <SDL/SDL.h> #include <SDL2/SDL.h> error: ‘SDL_GetKeyboardState’ was not declared in this scope const Uint8 *keystate = SDL_GetKeyboardState(NULL); ^ or #include <SDL2/SDL.h> #include <SDL/SDL.h> error: ‘SDL_Overlay’ was not declared in this scope SDL_Overlay *bmp; ^ Even adding #include <SDL2/SDL_video.h> does not solve the problem. What header should I add to use SDL_Overlay?
How do I use user_regs_struct on ARM processor in ptrace-based debugger
I am following the code in Chapter 3 of "Learning Linux Binary Analysis". The code is, "A simple ptrace-based debugger". I am trying to write this in my Raspberry Pi 3, which has an ARM processor. I know that the error means that I have not included the correct header file, but I cannot find what the correct header file is. I get this error message: field ‘pt_reg’ has incomplete type struct user_regs_struct pt_reg After doing some research, I found asm/ptrace.h, which includes some macros for the registers struct specific to ARM. Am I on the right track? How in the world can I make this work with an ARM processor? Here are the headers: #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <signal.h> #include <elf.h> #include <sys/types.h> #include <sys/user.h> #include <sys/stat.h> #include <sys/ptrace.h> #include <sys/mman.h> typedef struct handle { Elf64_Ehdr *ehdr; Elf64_Phdr *phdr; Elf64_Shdr *shdr; uint8_t *mem; char *symname; Elf64_Addr symaddr; struct user_regs_struct pt_reg; char *exec; } handle_t;
‘sockaddr_in6_t’ undeclared error even after inclusing the header files
I have following simple piece of code, which is a part of ipv6 handling module in a big project. #include <ctype.h> #include <sys/select.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <net/if.h> #include <arpa/inet.h> #include <netdb.h> #include <sys/stat.h> int main(){ sockaddr_in6_t* pSadrIn6 = (sockaddr_in6_t*) malloc(sizeof sockaddr_in6_t); return 0; } It gives me following not error: error: ‘sockaddr_in6_t’ undeclared (first use in this function) Is there any special library installation or linking that I need to access the library?
It looks like you copied this code from the Linux IPv6 HOWTO but didn't copy the additional typedefs: /* ** Type definitions (for convenience). */ typedef enum { false = 0, true } boolean; typedef struct sockaddr_in sockaddr_in_t; typedef struct sockaddr_in6 sockaddr_in6_t; Personally I would just use the types as they are (instead of extra typedefs to avoid typing struct), but whatever