How to compile a user defined function in SQLite - c

I have an example C function that I would like to attach to a database temp.sqlite (it's from an O'Reilly book, so I know it works). I read the section in the book and sqlite.org, but they assume away that I know how and where to compile this thing with the proper settings. I'm on either Mac (with XCode) or Ubuntu.
I know enough C to alter the code to do what I want, but I have no idea what to do call it from my database temp.sqlite.
Thanks for your help! I've been churning on this!
Update: A few more hours in and I've scrapped together enough stuff from abandoned webpages to create a compile command and generate an error:
richard$ gcc -o wtavg wtavg.c -Wall -W -O2 -L/usr/local/lib -lsqlite3
wtavg.c: In function ‘wtavg_init’:
wtavg.c:63: warning: unused parameter ‘error’
Undefined symbols:
"_main", referenced from:
start in crt1.10.6.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
FWIW, here's wtavg.c, which is straight from the O'Reilly site provided in my book:
/* wtavg.c */
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1;
#include <stdlib.h>
typedef struct wt_avg_state_s {
double total_data; /* sum of (data * weight) values */
double total_wt; /* sum of weight values */
} wt_avg_state;
static void wt_avg_step( sqlite3_context *ctx, int num_values, sqlite3_value **values )
{
double row_wt = 1.0;
int type;
wt_avg_state *st = (wt_avg_state*)sqlite3_aggregate_context( ctx,
sizeof( wt_avg_state ) );
if ( st == NULL ) {
sqlite3_result_error_nomem( ctx );
return;
}
/* Extract weight, if we have a weight and it looks like a number */
if ( num_values == 2 ) {
type = sqlite3_value_numeric_type( values[1] );
if ( ( type == SQLITE_FLOAT )||( type == SQLITE_INTEGER ) ) {
row_wt = sqlite3_value_double( values[1] );
}
}
/* Extract data, if we were given something that looks like a number. */
type = sqlite3_value_numeric_type( values[0] );
if ( ( type == SQLITE_FLOAT )||( type == SQLITE_INTEGER ) ) {
st->total_data += row_wt * sqlite3_value_double( values[0] );
st->total_wt += row_wt;
}
}
static void wt_avg_final( sqlite3_context *ctx )
{
double result = 0.0;
wt_avg_state *st = (wt_avg_state*)sqlite3_aggregate_context( ctx,
sizeof( wt_avg_state ) );
if ( st == NULL ) {
sqlite3_result_error_nomem( ctx );
return;
}
if ( st->total_wt != 0.0 ) {
result = st->total_data / st->total_wt;
}
sqlite3_result_double( ctx, result );
}
int wtavg_init( sqlite3 *db, char **error, const sqlite3_api_routines *api )
{
SQLITE_EXTENSION_INIT2(api);
sqlite3_create_function( db, "wtavg", 1, SQLITE_UTF8,
NULL, NULL, wt_avg_step, wt_avg_final );
sqlite3_create_function( db, "wtavg", 2, SQLITE_UTF8,
NULL, NULL, wt_avg_step, wt_avg_final );
return SQLITE_OK;
}

The user defined function should be compiled as shared library file:
gcc -shared -fPIC -o wtavg.so wtavg.c -lsqlite3
That shared library can then be loaded using an SQLite statement:
SELECT load_extension('/path/to/wt_avg.so', 'wtavg_init');
Unfortunately the version of sqlite3 provided by Apple doesn't support loading shared libraries. You can use sqlite from MacPorts instead. MacPorts programs linking against sqlite should also have the ability to load user defined functions this way.
When using SQLite inside another program however the extension loading mechanism may be disabled for security reasons. In Python for instance you have to call con.enable_load_extension(True) to enable it.

Related

SDL_GL_ExtensionsSupported alway returns SDL_False

According to the SDL2 documentation, you should always ask when you load an OpenGL extension whether the extension is supported. See: https://wiki.libsdl.org/SDL_GL_GetProcAddress
I'm on KUbuntu 16.04, but also want to support other platforms,
Currently I'm always getting a valid pointer to an extension, but SDL_GL_ExtensionSupported always tells that it is not supported.
I use CMake to find the opengl libraries via FindPackage(OpenGL REQUIRED) and then link to them via.
target_link_libraries(MyTarget ${OPENGL_gl_LIBRARIES})
If I ask glewinfo:
$glewinfo | grep -i glcompileshader
glCompileShader: OK
glCompileShaderARB: OK
glCompileShaderIncludeARB: OK
I'm Opening a window with:
SDL_Window* window;
SDL_GLContext context;
int flags = SDL_WINDOW_RESIZABLE|SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN;
window = SDL_CreateWindow("name", x, y, z, flags);
context = SDL_GL_CreateContext(window);
And then I call allocate_glextension_for_context(context);
from the fragment below.
// casting function pointers generates pedantic errors
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#define LOAD_AND_CHECK_EXTENSION(name) \
ext->name = (ext_##name) SDL_GL_GetProcAddress(#name); \
if (ext->name != NULL) { \
if (SDL_GL_ExtensionSupported(#name) != SDL_TRUE) { \
ext->name = NULL; \
failed_to_load = 1; \
fprintf(stderr, "failed to load %s\n", #name); \
} \
} \
/**
* \brief This function loads the extensions for a given context.
*
* #param [in] The SDL_GLContext that should be active.
* #param extensions The set of extensions.
* #return PSY_GL_LOAD_OK if everything is alright.
*/
static int
load_extentions(GLExtensions* ext)
{
int failed_to_load = 0;
// Here below we load functions from the opengl library via SDL2
// via a macro, this is roughly what it does.
ext->glShaderSource = SDL_GL_GetProcAddress("glShaderSource");
if (ext->glShaderSource != NULL) {
if (SDL_GL_ExtensionSupported("glShaderSource") != SDL_TRUE) {
ext->glShaderSource = NULL;
failed_to_load = 1;
}
}
// Is already done here above.
//LOAD_AND_CHECK_EXTENSION(glShaderSource);
LOAD_AND_CHECK_EXTENSION(glCompileShader);
LOAD_AND_CHECK_EXTENSION(glGetShaderiv);
LOAD_AND_CHECK_EXTENSION(glGetShaderInfoLog);
if (failed_to_load)
return PSY_GL_LOAD_EXTENSION_MISSING;
else
return PSY_GL_LOAD_OK;
}
//reenable all warnings
#pragma GCC diagnostic pop
int
allocate_glextension_for_context(SDL_GLContext context)
{
ExtensionPair pair = {
.context = context,
.extensions = {0}
};
int ret;
if (context != SDL_GL_GetCurrentContext())
return PSY_GL_LOAD_CONTEXT_NOT_CURRENT;
if (g_array) {
for (size_t i = 0; i < see_dynamic_array_size(g_array); i++) {
ExtensionPair* pair = see_dynamic_array_get(g_array, i);
if (pair->context == context)
return PSY_GL_LOAD_CONTEXT_EXISTS;
}
}
else {
ret = see_dynamic_array_new(
&g_array,
sizeof (ExtensionPair),
NULL,
NULL,
NULL
);
if (ret != SEE_SUCCESS)
return PSY_GL_LOAD_NO_MEMORY;
}
ret = load_extentions(&pair.extensions);
if (see_dynamic_array_add(g_array, &pair) != SEE_SUCCESS)
return PSY_GL_LOAD_NO_MEMORY;
return ret;
}
If I run the code I always get and many others:
failed to load glCompileShader
Indictating that SDL_ExtensionSupported("glCompileShader") returns SDL_False...
However, above I showed that glew indicates that these extensions are all supported. What am I doing wrongly?
There's no extension called "glShaderSource".
GL extension strings generally look something like this: GL_EXT_framebuffer_blit
glShaderSourceARB was added by ARB_shader_objects but has been a core feature since OpenGL 2.0.
Unless you're targeting pre-2.0 GL implementations and actually plan on supporting the ARB entry-points I recommend doing a GL version check instead.

SQLite: wrong call of sqlite3_prepare_v2 -> SIGSEGV

I've got stuck on my homework with SQLite. I use 2 columns; the first for product, the second for count. A user adds new products, which updates the count. We have to control, that the user doesn't add the same product again, or prevent him from picking more units than are available. We have to use it frequently, so I created functions:
int exists(char *param, sqlite3** ppDb) //0 if product exists
{
int error = 0;
char *a = NULL;
sqlite3_stmt **ppStmt = NULL;
const char **pzTail = NULL;
char *zSQL = sqlite3_mprintf("SELECT 'products' FROM 'table' WHERE 'products' LIKE '%q'", param);
//HERE IT FALS
error = sqlite3_prepare_v2(
*ppDb, /* Database handle */
zSQL, /* SQL statement, UTF-8 encoded */
(sizeof(zSQL)+1), /* Maximum length of zSql in bytes. */
ppStmt, /* OUT: Statement handle */
pzTail /* OUT: Pointer to unused portion of zSql */
);
sqlite3_free(zSQL);
a = (char*) sqlite3_column_text(*ppStmt, 0);
return strcmp(a, param); //0 if same -> product is in db yet
}
//similar one for count
Call
int main(int argc, const char *argv[])
{
sqlite3 *pDb;
int error = 0;
//parsing input
error = sqlite3_open(argv[1], &pDb);
if (error == 0)
{
sqlite3_exec(
pDb, /* An open database */
"CREATE TABLE 'table' ('products', 'quantity')", /* SQL */
0, /* Callback function */
NULL, /* 1st argument to callback */
NULL /* Error msg written here */
);
if (exists(param[1], &pDb) == 0)
{
fprintf (stderr, "ERROR: Product exists yet\n");
}
else
{
char *zSQL = sqlite3_mprintf("INSERT INTO 'table' VALUES ('%q', '0')", param[1]);
error = sqlite3_exec(
pDb, /* An open database */
zSQL, /* SQL to be evaluated */
0, /* Callback function */
NULL, /* 1st argument to callback */
NULL /* Error msg written here */
);
sqlite3_free(zSQL);
if (error == 0) printf("Added\n");
else printf("%i", error);
}
}
else return 1;
return 0;
}
It fails on sqlite3_prepare_v2. I expect there is a problem with the pointer on pDb, but I wasn't able to fix it (I'm not fan of pointers - too strong a tool for beginner). When it fails, the debugger stacked on line 93396 in sqlite3.c (*ppStmt = 0; - it writes somewhere, where it should'nt).
Compiled on linux x64:
gcc -std=c99 -Wall -pedantic -Wextra -Werror -DSQLITE_THREADSAFE=0 -ldl -o sqlite main.c sqlite3.c
Nothing wrong (if I've copied wrongly brackets, ignore it - it's not the problem), SQLite 3.7.14.1
Sorry for my English, I'm from Czech.
sqlite3_prepare_v2 wants to write the statement pointer into your output variable, but you are not giving it a pointer to this pointer variable, you are giving it a NULL pointer.
Use:
sqlite3_stmt *pStmt;
sqlite3_prepare_v2(..., &pStmt, ...);
Also note that identifiers should be quoted with "double quotes" or [brackets] or
`backticks`
but not with 'single quotes', which are used for literal strings.

How do I callback to a function that is inside the exe?

I have a written code for Windows, and now am trying to port to Linux, but not sure if it is possible or not.
My Question: I am trying to callback to a function that is in the executable from the shared library. How do I do that?
This is the compilation output:
Output:
build/release-linux-ppc64/ioq3ded.ppc64
build/release-linux-ppc64/ioquake3.ppc64
build/release-linux-ppc64/baseq3/cgameppc64.so
build/release-linux-ppc64/baseq3/qagameppc64.so
build/release-linux-ppc64/baseq3/uippc64.so
build/release-linux-ppc64/missionpack/cgameppc64.so
build/release-linux-ppc64/missionpack/qagameppc64.so
build/release-linux-ppc64/missionpack/uippc64.so
make[2]: Entering directory `/r/home7/XXX/ioquake3'
make[2]: `build/release-linux-ppc64/ioq3ded.ppc64' is up to date.
make[2]: `build/release-linux-ppc64/ioquake3.ppc64' is up to date.
LD build/release-linux-ppc64/baseq3/cgameppc64.so
LD build/release-linux-ppc64/baseq3/qagameppc64.so
LD build/release-linux-ppc64/baseq3/uippc64.so
LD build/release-linux-ppc64/missionpack/cgameppc64.so
LD build/release-linux-ppc64/missionpack/qagameppc64.so
LD build/release-linux-ppc64/missionpack/uippc64.so
This is the command that I run to execute my program, that is why I figured "ioq3ded.ppc64" to be my EXECUTABLE.
./ioq3ded.ppc64 +set fs_game Mod +set sv_pure 0 +set vm_game 0 +set vm_cgame 0 +set vm_ui 0 +set dedicated 1 +exec something_117.cfg
This is the code for Windows:
//Called function
__declspec(dllexport) void UnLinkLinkroutingcache( void )
{
//code
}
//Callback location
#include<windows.h>
typedef void (* fUnLinkLinkroutingcache_t)( void );
void fUnLinkLinkroutingcache( fUnLinkLinkroutingcache_t pUnLinkLinkroutingcache )
{
pUnLinkLinkroutingcache(); return;
}
fUnLinkLinkroutingcache_t pUnLinkLinkroutingcache;
void callUnlinkLink(void)
{
HMODULE hLib;
//fUnLinkLinkroutingcache_t pUnLinkLinkroutingcache;
hLib = LoadLibrary(TEXT("ioquake3.exe"));
if (hLib == NULL)
{
//Module not found, permission denied, ...
return 0; //inform caller of error
}
pUnLinkLinkroutingcache = (fUnLinkLinkroutingcache_t)GetProcAddress(hLib, TEXT("UnLinkLinkroutingcache"));
if ( pUnLinkLinkroutingcache == NULL)
{
return 0;
}
fUnLinkLinkroutingcache(pUnLinkLinkroutingcache);
}
I tried to port this code to Linux, but I can't seem to load the exe.
//Called function
extern void UnLinkLinkroutingcache( void )
//Callback location
void callUnlinkLink(void)
{
void* handle;
void (*initializer)(void);
FILE *fp;//zgzg2020
fp = fopen("HereIsMe.txt", "a");
if( fp != NULL )
{
fprintf(fp, "%d", 1 );
fprintf(fp, "\n" );
}
fclose(fp);
handle = dlopen("./ioq3ded.ppc64", RTLD_LAZY);
if(handle == NULL) {
// report error ...
fp = fopen("ICantFindFile.txt", "a");
if( fp != NULL )
{
fprintf(fp, "%d", 1 );
fprintf(fp, "\n" );
}
fclose(fp);
exit(1);return;
} else {
initializer = dlsym(handle,"UnLinkLinkroutingcache");
if(initializer == NULL) {
// report error ...
fp = fopen("ICantFindFfunction.txt", "a");
if( fp != NULL )
{
fprintf(fp, "%d", 1 );
fprintf(fp, "\n" );
}
fclose(fp);
exit(1);return;
} else {
// cast initializer to its proper type and use
(*initializer)();
}
// use the result in a call to dlsym
}
}
Unfortunately, dlopen will not suffice for this purpose as many other posters have said. It's only capable of loading shared libraries. If you pass NULL instead of a shared library path, you can look up any symbols that the run-time linker has not stripped from the main executable image (there aren't many).
However, if you want to call functions within an executable compiled without -rdynamic, try LD_PRELOAD'ing your own shared library that (on startup) locates the real path to your executable file via /proc/self/exe, memory maps it, and then reads the symbol table on that mapping (or other executable headers) to locate and interpret symbols within the main executable.
From there, it's just a matter of defining a few function pointers in your shared library that match the prototype of the function you wish to call, assigning them the location of the symbol in the binary, and calling the function pointer as normal.
You can't dlopen executables in Linux -- the function only works on shared libraries (.so, roughly equivalent to .dll on Windows).
What are you trying to accomplish?
If ioq3ded.ppc64 is really a .so (doesn't look like it), have you checked what it exports?
Have you checked errno when you get a null return from dlopen (assuming it is a .so file here, as #duskwuff says, everything else would fail)?
The function dlopen() loads the dynamic library file named by the null-terminated string filename and returns an opaque "handle" for the dynamic library. If filename is NULL, then the returned handle is for the main program. Which does mean it has to be dynamic library.

C library gives '__gxx_personality_v0 ' error in Postgres

I'm building a new 64bit Debian Squeeze server, and Postgres 8.4 reports the well documented 'undefined __gxx_personality_v0' error when I try to restore a database.
The lib builds/installs fine.
However, the source is c, not c++ which seems to be where __gxx_personality_v0 belongs.
The code is from a 32bit Etch/postgres 8.1 environmnet.
I'm kind of stuck - but I bet the solution is very simple!
Test to see whether the issue is actually related to PostgreSQL, or if it is a problem with your library build. Here's a simple program you can use to dlopen() your library and resolve a symbol. Compile it with:
gcc dlopentest.c -o dlopentest -ldl
... and run it as:
./dlopentest /path/to/my/lib.so somesymbol
or for more info prefix LD_DEBUG=symbols (for other options LD_DEBUG=help) eg:
LD_DEBUG=symbols ./dlopentest /path/to/my/lib somesymbol
Which symbol to look for depends on your code and what it's for. You haven't provided enough information to say.
This test program won't work with any library that requires symbols from the postgresql executable in order to load and init, so if your code is (for example) a procedural language it won't load. Most simple modules load fine, though.
You should also examine the output of:
ldd /path/to/your/library.so
to see if it's linking to libstdc++ or anything else you don't expect.
Here's the test program:
// Compile with a c99 compiler; I don't use oldstyle declarations
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char * argv[]) {
if (argc != 3) {
printf("Usage: %s /path/to/lib/to/load symbol_to_resolve\n", argv[0]);
printf(" eg: %s libc.so.6 gettimeofday\n", argv[0]);
return 1;
}
char * err;
const char * const libname = argv[1];
const char * const symname = argv[2];
dlerror(); // clear dl error state before starting work
void * libhandle = dlopen(libname, RTLD_LAZY);
if ( (err = dlerror()) != NULL ) {
printf("Failed to load library: %s\n", err);
return 2;
}
void * symhandle = dlsym(libhandle, symname);
if ( (err = dlerror()) != NULL ) {
printf("Failed to load symbol: %s\n", err);
return 2;
}
printf("Successfully retrieved symbol %s from library %s\n", symname, libname);
// Optional since we're existing, but good for testing:
if ( (err = dlerror()) != NULL ) {
printf("Failed to close lib during exit: %s\n", err);
return 2;
}
return 0;
}

Can repeating C source code causing compile errors?

As per another question I had asked earlier I think I may have found my problem but I need an experts eye.
I found the file /net/ipv4/tcp_zero_copy.c which was causing a compile failure of my kernel.
I no very little about C or C++, when I look at the file in my C/C++ editor it looks like the same code is repeating over over over (I think 4 times).
My question is simple;
Would that be enough to cause a problem with the compiler? If the same code showed up over and over in the same file?
Here is the source code of the file (from end to end 148 lines in total);
/*
* Support routines for TCP zero copy transmit
*
* Created by Vladislav Bolkhovitin
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include <linux/skbuff.h>
net_get_page_callback_t net_get_page_callback __read_mostly;
EXPORT_SYMBOL(net_get_page_callback);
net_put_page_callback_t net_put_page_callback __read_mostly;
EXPORT_SYMBOL(net_put_page_callback);
/*
* Caller of this function must ensure that at the moment when it's called
* there are no pages in the system with net_priv field set to non-zero
* value. Hence, this function, as well as net_get_page() and net_put_page(),
* don't need any protection.
*/
int net_set_get_put_page_callbacks(
net_get_page_callback_t get_callback,
net_put_page_callback_t put_callback)
{
int res = 0;
if ((net_get_page_callback != NULL) && (get_callback != NULL) &&
(net_get_page_callback != get_callback)) {
res = -EBUSY;
goto out;
}
if ((net_put_page_callback != NULL) && (put_callback != NULL) &&
(net_put_page_callback != put_callback)) {
res = -EBUSY;
goto out;
}
net_get_page_callback = get_callback;
net_put_page_callback = put_callback;
out:
return res;
}
EXPORT_SYMBOL(net_set_get_put_page_callbacks);
/*
* Support routines for TCP zero copy transmit
*
* Created by Vladislav Bolkhovitin
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include <linux/skbuff.h>
net_get_page_callback_t net_get_page_callback __read_mostly;
EXPORT_SYMBOL(net_get_page_callback);
net_put_page_callback_t net_put_page_callback __read_mostly;
EXPORT_SYMBOL(net_put_page_callback);
/*
* Caller of this function must ensure that at the moment when it's called
* there are no pages in the system with net_priv field set to non-zero
* value. Hence, this function, as well as net_get_page() and net_put_page(),
* don't need any protection.
*/
int net_set_get_put_page_callbacks(
net_get_page_callback_t get_callback,
net_put_page_callback_t put_callback)
{
int res = 0;
if ((net_get_page_callback != NULL) && (get_callback != NULL) &&
(net_get_page_callback != get_callback)) {
res = -EBUSY;
goto out;
}
if ((net_put_page_callback != NULL) && (put_callback != NULL) &&
(net_put_page_callback != put_callback)) {
res = -EBUSY;
goto out;
}
net_get_page_callback = get_callback;
net_put_page_callback = put_callback;
out:
return res;
}
EXPORT_SYMBOL(net_set_get_put_page_callbacks);
/*
* Support routines for TCP zero copy transmit
*
* Created by Vladislav Bolkhovitin
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include <linux/skbuff.h>
net_get_page_callback_t net_get_page_callback __read_mostly;
EXPORT_SYMBOL(net_get_page_callback);
net_put_page_callback_t net_put_page_callback __read_mostly;
EXPORT_SYMBOL(net_put_page_callback);
/*
* Caller of this function must ensure that at the moment when it's called
* there are no pages in the system with net_priv field set to non-zero
* value. Hence, this function, as well as net_get_page() and net_put_page(),
* don't need any protection.
*/
int net_set_get_put_page_callbacks(
net_get_page_callback_t get_callback,
net_put_page_callback_t put_callback)
{
int res = 0;
if ((net_get_page_callback != NULL) && (get_callback != NULL) &&
(net_get_page_callback != get_callback)) {
res = -EBUSY;
goto out;
}
if ((net_put_page_callback != NULL) && (put_callback != NULL) &&
(net_put_page_callback != put_callback)) {
res = -EBUSY;
goto out;
}
net_get_page_callback = get_callback;
net_put_page_callback = put_callback;
out:
return res;
}
EXPORT_SYMBOL(net_set_get_put_page_callbacks);
** EDIT **
Also I just used Notepad++ to compare the individual blocks of code where it looked like they ended. According to the compare tool all 3 block match each other.
Here is the compiler output from the place it died to the command prompt it returned to me.
CC net/ipv4/tcp_zero_copy.o
net/ipv4/tcp_zero_copy.c:63:1: error: redefinition of â__kcrctab_net_get_page_callbackâ
net/ipv4/tcp_zero_copy.c:14:1: note: previous definition of â__kcrctab_net_get_page_callbackâ was here
net/ipv4/tcp_zero_copy.c:63:1: error: redefinition of â__kstrtab_net_get_page_callbackâ
net/ipv4/tcp_zero_copy.c:14:1: note: previous definition of â__kstrtab_net_get_page_callbackâ was here
net/ipv4/tcp_zero_copy.c:63:1: error: redefinition of â__ksymtab_net_get_page_callbackâ
net/ipv4/tcp_zero_copy.c:14:1: note: previous definition of â__ksymtab_net_get_page_callbackâ was here
net/ipv4/tcp_zero_copy.c:66:1: error: redefinition of â__kcrctab_net_put_page_callbackâ
net/ipv4/tcp_zero_copy.c:17:1: note: previous definition of â__kcrctab_net_put_page_callbackâ was here
net/ipv4/tcp_zero_copy.c:66:1: error: redefinition of â__kstrtab_net_put_page_callbackâ
net/ipv4/tcp_zero_copy.c:17:1: note: previous definition of â__kstrtab_net_put_page_callbackâ was here
net/ipv4/tcp_zero_copy.c:66:1: error: redefinition of â__ksymtab_net_put_page_callbackâ
net/ipv4/tcp_zero_copy.c:17:1: note: previous definition of â__ksymtab_net_put_page_callbackâ was here
net/ipv4/tcp_zero_copy.c:74:5: error: redefinition of ânet_set_get_put_page_callbacksâ
net/ipv4/tcp_zero_copy.c:25:5: note: previous definition of ânet_set_get_put_page_callbacksâ was here
net/ipv4/tcp_zero_copy.c:98:1: error: redefinition of â__kcrctab_net_set_get_put_page_callbacksâ
net/ipv4/tcp_zero_copy.c:49:1: note: previous definition of â__kcrctab_net_set_get_put_page_callbacksâ was here
net/ipv4/tcp_zero_copy.c:98:1: error: redefinition of â__kstrtab_net_set_get_put_page_callbacksâ
net/ipv4/tcp_zero_copy.c:49:1: note: previous definition of â__kstrtab_net_set_get_put_page_callbacksâ was here
net/ipv4/tcp_zero_copy.c:98:1: error: redefinition of â__ksymtab_net_set_get_put_page_callbacksâ
net/ipv4/tcp_zero_copy.c:49:1: note: previous definition of â__ksymtab_net_set_get_put_page_callbacksâ was here
make[2]: *** [net/ipv4/tcp_zero_copy.o] Error 1
make[1]: *** [net/ipv4] Error 2
make: *** [net] Error 2
root#dev01:/usr/src/linux# ls
It depends on what is being repeated,
A function declaration repeated won't give any errors.
A function definition repeated would give errors.
A variable being created\defined with same name would give errors.
#2 & #3 give errors as they break the ODR(One Definition Rule).
void doSomething(); //no error
void doSomething();
void doSomething();
void doSomething()
{
}
int main()
{
int i; //error
int i;
doSomething();
return 1;
}
In this code:
net_get_page_callback_t net_get_page_callback __read_mostly;
defines an variable and doing so repeatedly, leads to multiple definition of same named variable and hence the redefinition error.
It is an error for a function to be multiply defined in a translation unit. That is what happens here. Try posting the first few error messages from compilation.

Resources