How to fix clang handle_out_of_bounds error - c

I'm currently compiling my C99 code with clang's compiler flag -fsanitize=array-bounds and it produced a "__ubsan_handle_out_of_bounds" error here:
void _add_entry(const char* api_name, void* api_ptr) {
int id = _produce_id_from_string(api_name);
ASSERT(_api_hash_map.entry_index < MAX_ENTRIES);
_key_value_pair* map_entry = &_api_hash_map.entries[_api_hash_map.entry_index++]; //out of bounds
map_entry->unique_id = id;
map_entry->value = (uintptr)api_ptr;
};
So I tried putting the `_api_hash_map.entry_index' inside an if to get rid of the error:
void _add_entry(const char* api_name, void* api_ptr) {
int id = _produce_id_from_string(api_name);
ASSERT(_api_hash_map.entry_index < MAX_ENTRIES);
if(_api_hash_map.entry_index < MAX_ENTRIES) {
_key_value_pair* map_entry = &_api_hash_map.entries[_api_hash_map.entry_index];
map_entry->unique_id = id;
map_entry->value = (uintptr)api_ptr;
_api_hash_map.entry_index++;
}
};
but to no avail. To check, I simplified things further and just wrote:
void _add_entry(const char* api_name, void* api_ptr) {
int arr[10] = { 0 };
arr[3] = 23;
};
but still receive the error. I must be misunderstanding how -array-bounds checking works in clang. What am I missing
Edit:
My current build file for clang is:
#echo off
REM This represents the full directory path to your batch file
set cwd=%~dp0
call "C:\msvc\setup.bat"
REM -fno-stack-protector tells compiler to not worry about security calls (like __security_cookie) that would typically be inserted with c libs. -mstack-probe-size=99999999999 basically says don't worry about __chkdsk for checking stack overruns
REM Note that the -Wpadded option isn't really working at the moment. I think there is a github issue on this open so we'll have to see if this is fixed in a later version (https://github.com/llvm/llvm-project/issues/58100)
set compiler_flags=-g -fdebug-macro -O0 -fno-stack-protector -Wall -Wpadded -mstack-probe-size=9999999 -fno-builtin -std=c99 -fdiagnostics-absolute-paths -fsanitize=array-bounds
REM -STACK:0x100000,0x100000 is setting function stack default to 1MB. Can increase this if we need to. Keep in mind though this also increases default stack size for all threads created
set linker_flags=-subsystem:windows -machine:x64 -incremental:no -opt:ref -debug:full -ignore:4099 -NODEFAULTLIB -STACK:0x100000,0x100000
set include_paths=-I"%cwd%source" -I"C:\msvc\Windows Kits\10\Include\10.0.22621.0\um"
set library_paths=-LIBPATH:"C:\msvc\Windows Kits\10\Lib\10.0.22621.0\um\x64"
set import_libraries="kernel32.lib" "user32.lib" "glew32s.lib" "opengl32.lib" "gdi32.lib"
IF NOT EXIST bin mkdir bin
pushd bin
clang --compile ..\source\editor.c %compiler_flags%
lld-link editor.o -dll %linker_flags% -export:editor_update -noentry
clang --compile ..\source\win64_main.c %compiler_flags% %include_paths% -I"%cwd%dep\glew-2.1.0\include" -DBGZ_WIN64 -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable -Wno-null-dereference
lld-link win64_main.o -OUT:win64_main.exe %linker_flags% %library_paths% %import_libraries% -LIBPATH:"%cwd%dep\glew-2.1.0\lib\win64-release"
The error I'm receiving is:
----- Build Debug x64 -----
Executing build command:
clang_build.bat
lld-link: error: undefined symbol: __ubsan_handle_out_of_bounds
>>> referenced by D:\User Program Files_Data\software_projects\bgz_engine\source\api_directory.h:52
>>> win64_main.o:(_add_entry)
>>> referenced by D:\User Program Files_Data\software_projects\bgz_engine\source\api_directory.h:74
>>> win64_main.o:(_get_api)
>>> referenced by D:\User Program Files_Data\software_projects\bgz_engine\source\stb_sprintf.h:595
>>> win64_main.o:(stbsp_vsprintfcb)
>>> referenced 209 more times
===== Success : 1 errors, 0 warnings =====

Related

Why does GCC 9.1.0 sometimes complain about this use of strncpy()?

This is a 40-line MCVE (Minimal, Complete, Verifiable Example) — or something close to minimal — cut down from a 1675 line source file that originally included 32 headers (and most of those included multiple other headers — compiling it with gcc -H lists 464 headers from the project and the system, many of them several times). That file is working code that previously compiled without warnings (GCC 8.3.0), but not with GCC 9.1.0. All structure, function, type, variable names have been changed.
pf31.c
#include <string.h>
enum { SERVERNAME_LEN = 128 };
typedef struct ServerQueue
{
char server_name[SERVERNAME_LEN + 1];
struct ServerQueue *next;
} ServerQueue;
extern int function_under_test(char *servername);
#ifdef SUPPRESS_BUG
extern int function_using_name(char *name);
#endif /* SUPPRESS_BUG */
extern int GetServerQueue(const char *servername, ServerQueue *queue);
int
function_under_test(char *servername)
{
ServerQueue queue;
char name[SERVERNAME_LEN + 1];
if (GetServerQueue(servername, &queue) != 0)
return -1;
char *name_in_queue = queue.server_name;
if (name_in_queue)
strncpy(name, name_in_queue, SERVERNAME_LEN);
else
strncpy(name, servername, SERVERNAME_LEN);
name[SERVERNAME_LEN] = '\0';
#ifdef SUPPRESS_BUG
return function_using_name(name);
#else
return 0;
#endif /* SUPPRESS_BUG */
}
Compilation
When compiled using GCC 9.1.0 (on a Mac running macOS 10.14.5 Mojave, or on a Linux VM running RedHat 5.x — don't ask!), with the option -DSUPPRESS_BUG I get no error, but with the option -USUPPRESS_BUG, I get an error:
$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -DSUPPRESS_BUG -c pf31.c
$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -USUPPRESS_BUG -c pf31.c
In file included from /usr/include/string.h:417,
from pf31.c:1:
pf31.c: In function ‘function_under_test’:
pf31.c:30:9: error: ‘__builtin_strncpy’ output may be truncated copying 128 bytes from a string of length 128 [-Werror=stringop-truncation]
30 | strncpy(name, name_in_queue, SERVERNAME_LEN);
| ^~~~~~~
cc1: all warnings being treated as errors
$
When I compile using GCC 8.3.0, I get no errors reported.
Question
Two sides of one question:
Why does GCC 9.1.0 complain about the use of strncpy() when the code is compiled with -USUPPRESS_BUG?
Why doesn't it complain when the code is compiled with -DSUPPRESS_BUG?
Corollary: is there a way to work around this unwanted warning that works with older GCC versions as well as 9.1.0. I've not yet found one. There's also a strong element of "I don't think it should be necessary, because this is using strncpy() to limit the amount of data copied, which is what it is designed for".
Another variant
I have another non-erroring variant, changing the signature of the function_under_test() — here's a set of diffs:
11c11
< extern int function_under_test(char *servername);
---
> extern int function_under_test(char *servername, ServerQueue *queue);
20c20
< function_under_test(char *servername)
---
> function_under_test(char *servername, ServerQueue *queue)
22d21
< ServerQueue queue;
25c24
< if (GetServerQueue(servername, &queue) != 0)
---
> if (GetServerQueue(servername, queue) != 0)
27c26
< char *name_in_queue = queue.server_name;
---
> char *name_in_queue = queue->server_name;
This compiles cleanly regardless of whether SUPPRESS_BUG is defined or not.
As you can guess from the SUPPRESS_BUG terminology, I'm tending towards the view that this is bug in GCC, but I'm kinda cautious about claiming it is one just yet.
More about the the original code: the function itself was 540 lines long; the strncpy() block occurs about 170 lines into the function; the variable corresponding to name was used further down the function in a number of function call, some of which take name as an argument and supply a return value for the function. This corresponds more to the -DSUPPRESS_BUG code, except that in the 'real code', the bug is not suppressed.
This is a GCC bug tracked as PR88780. According to Martin's comment, this warning did not exist prior to GCC 8.
GCC is shipped with this known bug, as it is not deemed release-critical.
To be honest, I am not 100% sure it is the bug. The point is, there are known false-positives. If you feel like helping the GCC project, you can find the most appropriate bug among strncpy / Wstringop-truncation bugs and post your example there. It would be more helpful if you minimized it further (say, with creduce); minimizing the compile string is also appreciated (that would be rather trivial, I guess).
Several compilation warnings related to strncpy were found in GCC 9.0 and reported here and here.
One of them is the error mentioned in the question which seems to occur in the file string_fortified.h:
/usr/include/bits/string_fortified.h:106:10: warning: ‘__builtin_strncpy’ output may be truncated copying 16 bytes from a string of length 16 [-Wstringop-truncation]
106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The response to this was given on April 15, 2019 was:
Thank you for the report, however as GCC 9 still under development. We do not see the above errors in the current stable GCC 7.4 or GCC 8.3. We appreciate the advanced notice, and will accept PRs to fix issues against GCC 9, but for now our target compiler is gcc stable.
So I believe the errors are probably a result of versions 9 and 9.1 being not stable versions. Hopefully they will be eliminated when these versions become stable.

Encoding Url In C With Line Breaks?

I've got this url encoder I found on the internet and made few small changes, however when ever I do something such as this:
char encodedWord[100];
const char* word = "Stack\nOverflow";
urlencode(encodedWord, word);
The output would be something like this:
"Stack0X8.51EE00001674P-1022Overflow" instead of x0A in between of Stack Overflow.
Why is it outputting that? I assume because of the "EE0000" part something went wrong with the char to number conversion.
How can I get my encoder to be much more friendly to special characters? i.e "\n,\r,\r".
The Function
int urlencode(char *dest, const char *src)
{
/* urlencode all non-alphanumeric characters in the C-string 'src'
store result in the C-string 'dest'
return the length of the url encoded C-string
*/
char *d;
int i;
for(i=0, d=dest; src[i]; i++) {
if(isalnum(src[i]) || isdigit(src[i])) {
*(d++) = src[i];
} else {
snprintf(d, 4, "%%%02X", src[i]);
d += 3;
}
}
*d = 0;
return d-dest;
}
System
Windows 10 32bit
Mingw32 (gcc 5.1.0)
Make File
#OBJS specifies which files to compile as part of the project
OBJS = $(wildcard ./src/*.c)
#CC specifies which compiler we're using
CC = gcc
#INCLUDE_PATHS specifies the additional include paths we'll need
INCLUDE_PATHS =
#LIBRARY_PATHS specifies the additional library paths we'll need
LIBRARY_PATHS =
#COMPILER_FLAGS specifies the additional compilation options we're using
# -w suppresses all warnings
# -Wl,-subsystem,windows gets rid of the console window
COMPILER_FLAGS = -Wall -Wl,-subsystem,console -std=c99
#LINKER_FLAGS specifies the libraries we're linking against
LINKER_FLAGS = -lmingw32 -lws2_32 -lwininet -s -lshlwapi
#OBJ_NAME specifies the name of our executable
OBJ_NAME = project
#This is the target that compiles our executable
all : clean build
build:
cls
$(CC) $(OBJS) $(INCLUDE_PATHS) $(LIBRARY_PATHS) $(COMPILER_FLAGS) $(LINKER_FLAGS) -o $(OBJ_NAME)
clean:
del -f $(OBJ_NAME).exe
the urlencode function is working just fine, the problem is how you're printing the output. I was in the middle of writing
0X8.51EE00001674P-1022 is a hexadecimal floating point number, what you would expect to see from a %A printf specifier.
when it struck me that the correct output has %0A in that exact position. Which means that you're making the mistake of passing a non-constant string as the first parameter of printf. Don't do printf(encodedWord); you should be using printf("%s", encodedWord) instead.

Return address GDB: .exe differs from .elf?

I'm using GDB to return an address of a local static variable in my c code (pressureResult2 in this case), this is working fine for the ARM output: The .elf file.
However, if I use a build configuration for windows, creating a .exe, the variable I'm asking for can't be found.
What I'm using for returning the address of the variable:
sensorOffset::pressureResult2
Code:
static void sensorOffset (uint8_t axle)
{
static int16_t pressureResult2 = 400;
int16_t pressureResult = 0;
if (axle == AXLE_FRONT)
{
/* Always copy the actual value first to the value with offset */
CtisMach.front.tPressureSensorOffset = CtisMach.front.tPressureAct;
.... and so on
Is someone known with this issue? Is the command different for a windows executable? Or am I just doing something wrong?
To get the most obvious ones out:
Can you read an global static?
Yes, no problem
Does GDB notice anything about debug symbol?
No, the usual "Reading symbol from file.exe .. done" appears.
Does it work with .elf?
Yes, it does.
To answer the comments:
The code is compiled with the following:
cflags := \
-O0 \
-g3 \
-Wall \
-c \
-MD \
-fmessage-length=0 \
-fpermissive \
-I/mingw/include \
-I/usr/include \
-I/local/include \
-D WINDOWS \
$(CONFIGFLAGS) \
$(INCLUDES)
lnkflags := \
-Wl,--enable-stdcall-fixup \
-static-libgcc \
-static-libstdc++ \
$(CONFIGFLAGS) \
$(EXT_LIBDIR)
od_flags := \
--dwarf
Since I already mentioned it doesn't complain about debug variables symbols and I can read the global statics as well this doesn't appear to be the issue, or am I wrong? It should complain about not having debug symbols without -g right? Edit: Andreas reproduced this situation, but I still can't seem to fix it.
To do anything useful with the variable:
static int16_t pressureResult2 = 0;
if (pressureResult2 < 100)
{
pressureResult2++;
}
else
{
pressureResult2 = 0;
}
NOTE: This is just an example, same problem counts for all local statics in the code (that is too large to dump on SO).
GDB response on "Info variables", my variable "pressureResult2" is placed in the category Non-debugging symbols, might this be the issue?:
To see if the -g flag is actually doing something, without -g:
p& randomvar
$1 = (<data variable, no debug info> *) 0x4eade2 <randomvar>
with -g
p& randomvar
$1 = (uint16_t *) 0x4eade2 <randomvar>
So it's active for sure, but its still not possible to return local statics.
The only remarkable things so far is how the variable I'm looking for is categorized into Non-debugging symbols.
Compiling the code snipped of Andreas works including returning the address of the variable, my own code however, not much.
Most likely, you need to add the -g flag to the compiler invocation to add debugging information, and remove optimization flags like -O2. Given the following .c source file, using a cygwin environment on MS Windows:
#include <stdio.h>
static int globalstatic = 512;
static void sensorOffset (uint8_t axle) {
static int16_t pressureResult2 = 400;
pressureResult2++;
printf("%d %d\n", globalstatic, pressureResult2);
}
int main() {
int i = 0;
for (i = 0; i < 10; i++) {
sensorOffset(42);
}
return 0;
}
When compiled to an .exe file with -O2, your observation is reproduceable - gdb recognizes the global static variable, but not the local one (even though -g was specified):
C:> gcc -g -O2 -Wall -pedantic -o static static.c
C:> gdb static.exe
(gdb) break main
(gdb) run
Breakpoint 1, main () at static.c:14
14 int main() { Breakpoint 1, 0x0000000100401128 in main ()
(gdb) print globalstatic
$1 = 512
(gdb) print sensorOffset::pressureResult2
No symbol "sensorOffset" in current context.
When removing the -O2 flag, gdb does recognize the local static variable:
C:> gcc -g -Wall -pedantic -o static static.c
C:> gdb static.exe
(gdb) break main
(gdb) run
Breakpoint 1, main () at static.c:12
12 int i = 0;
(gdb) print sensorOffset::pressureResult2
$1 = 400

Link errors using FANN

I'm trying to build a basic FANN (Fast Artificial Neural Network) project on Windows with MinGW. However, whenever I try to link the executable, I run into a bunch of undefined reference to errors. Interestingly, if I don't link the library at all, I get more errors, implying that at least some of the library is working. The code for the file I'm trying to compile and link is:
#include "doublefann.h"
int main() {
const unsigned int num_input_neurons = 9;
const unsigned int num_output_neurons = 1;
const unsigned int num_layers = 3;
const unsigned int num_hidden_neurons = 9;
const float desired_error = (const float) 0;
const unsigned int max_epochs = 500000;
const unsigned int epochs_between_reports = 1000;
struct fann *ann = fann_create_standard(num_layers,
num_input_neurons,
num_hidden_neurons,
num_output_neurons);
fann_set_activation_function_hidden(ann, FANN_SIGMOID_SYMMETRIC);
fann_set_activation_function_output(ann, FANN_SIGMOID_SYMMETRIC);
fann_train_on_file(ann,
"titanic-training.data",
max_epochs,
epochs_between_reports,
desired_error);
fann_save(ann, "titanic.net");
fann_destroy(ann);
return 0;
}
and the command I'm using to compile and link is:
gcc -Wall -Ifann\src\include titanic-train.c -Lfann\bin -lfanndouble -o titanic-train.exe
The errors I'm getting back are:
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0x7f): undefined reference to `fann_set_activation_function_hidden'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0x93): undefined reference to `fann_set_activation_function_output'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0xbf): undefined reference to `fann_train_on_file'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0xd3): undefined reference to `fann_save'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0xdf): undefined reference to `fann_destroy'
c:/fragileprograms/mingw-native/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o: bad reloc address 0x64 in section `.rdata'
c:/fragileprograms/mingw-native/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: final link failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
If I don't link the library at all, I instead get:
C:\Users\kunkelwe\AppData\Local\Temp\ccyOO3jL.o:titanic-train.c:(.text+0x67): undefined reference to `fann_create_standard'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0x7f): undefined reference to `fann_set_activation_function_hidden'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0x93): undefined reference to `fann_set_activation_function_output'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0xbf): undefined reference to `fann_train_on_file'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0xd3): undefined reference to `fann_save'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0xdf): undefined reference to `fann_destroy'
c:/fragileprograms/mingw-native/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o: bad reloc address 0x64 in section `.rdata'
c:/fragileprograms/mingw-native/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: final link failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
Edit:
As per Haroogan's request, I ran nm fanndouble.lib. The output is rather extensive, so rather than paste it all here, I've made it available via pastebin here: http://pastebin.com/raw.php?i=vybFhEcX
I'm not familiar with nm, but it appears that the missing symbols do exist in the file.
Edit #2:
The contents of doublefann.h are: http://pastebin.com/mrHKJi8C
and the contents of fann.h, which it includes are: http://pastebin.com/gTrHCYAg
Could the problem just be solved by recompiling the library with MinGW?
Edit #3:
Making the changes that Haroogan suggested worked! In addition to those changes, I had to modify the CMakeLists.txt file for FANN by adding:
if (WIN32)
ADD_DEFINITIONS(-DFANN_DLL_EXPORTS)
endif (WIN32)
Then, running cmake -G "MinGW Makefiles" and then mingw32-make in the root of the project produced a file, libdoublefann.dll, that when linked against and included in the directory of the .exe, allowed me, finally, to run my program.
In doublefann.h on the line #116:
#if (_MSC_VER > 1300)
change to:
#if (_MSC_VER > 1300) || defined(__MINGW32__) || defined(__MINGW64__)
Furthermore, on the line #121:
#if defined(_MSC_VER) && (defined(FANN_USE_DLL) || defined(FANN_DLL_EXPORTS))
change to:
#if (defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)) && \
(defined(FANN_USE_DLL) || defined(FANN_DLL_EXPORTS))

undefined reference to `main' in C

Hi I am getting below error while compiling a c code using gcc
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
I am trying to import the fftw() function into SystemVerilog. Here is my code
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <fftw3.h>
void fftw(double FFT_in[],int size)
{
double *IFFT_out;
int i;
fftw_complex *middle;
fftw_plan fft;
fftw_plan ifft;
middle = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*size);
IFFT_out = (double *) malloc(size*sizeof(double));
fft = fftw_plan_dft_r2c_1d(size, FFT_in, middle, FFTW_ESTIMATE); //Setup fftw plan for fft (real 1D data)
ifft = fftw_plan_dft_c2r_1d(size, middle, IFFT_out, FFTW_ESTIMATE); //Setup fftw plan for ifft
fftw_execute(fft);
fftw_execute(ifft);
printf("Input: \tFFT_coefficient[i][0] \tFFT_coefficient[i][1] \tRecovered Output:\n");
for(i=0;i<size;i++)
printf("%f\t%f\t\t\t%f\t\t\t%f\n",FFT_in[i],middle[i][0],middle[i][1],IFFT_out[i]/size);
fftw_destroy_plan(fft);
fftw_destroy_plan(ifft);
fftw_free(middle);
free(IFFT_out);
//return IFFT_out;
}
Here is a system Verilog code from where I am trying to call fftw
module top;
import "DPI-C" function void fftw(real FFT_in[0:11], int size);
real j [0:11];
integer i,size;
real FFT_in [0:11];
initial begin
size = 12;
FFT_in[0] = 0.1;
FFT_in[1] = 0.6;
FFT_in[2] = 0.1;
FFT_in[3] = 0.4;
FFT_in[4] = 0.5;
FFT_in[5] = 0.0;
FFT_in[6] = 0.8;
FFT_in[7] = 0.7;
FFT_in[8] = 0.8;
FFT_in[9] = 0.6;
FFT_in[10] = 0.1;
FFT_in[11] = 0.0;
$display("Entering in SystemVerilog Initial Block\n");
#20
fftw(FFT_in,size);
$display("Printing recovered output from system verilog\n");
//for(i=0;i<size;i++)
//$display("%f\t\n",(j[i])/size);
$display("Exiting from SystemVerilog Initial Block");
#5 $finish;
end
endmodule
Here is an irun command to compile both systemverilg and C files
# Compile the SystemVerilog files
fftw_test.sv
-access +rwc
# Generate a header file called _sv_export.h
-dpiheader _sv_export.h
# Delay compilation of fftw_test.c until after elaboration
#-cpost fftw_test_DPI.c -end
-I/home/fftw/local/include -L/home/ss69/fftw/local/lib fftw_test_DPI.c -lfftw3 -lm
# Redirect output of ncsc_run to a log file called ncsc_run.log
-log_ncsc_run ncsc_run.log
while running this command give below error:
building library run.so
ld: /home/fftw/local/lib/libfftw3.a(mapflags.o): relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/homefftw/local/lib/libfftw3.a: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: * [/home/ss69/DPI/./INCA_libs/irun.lnx8664.12.20.nc/librun.so] Error 1
ncsc_run: *E,TBBLDF: Failed to build test library
/home/DPI/./INCA_libs/irun.lnx8664.12.20.nc/librun.so
irun: *E,CCERR: Error during cc compilation (status 1), exiting.
When I simply try to compile C using gcc with below command:
gcc -g -Wall -Werror -I/home/fftw/local/include -L/home/ss69/fftw/local/lib \
fftw_test_DPI.c -lfftw3 -lm -o fftw_test_DPI
I get this error:
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../lib64/crt1.o: In function _start':
(.text+0x20): undefined reference tomain'
collect2: ld returned 1 exit status
Exactly how are you using the function void fftw(double FFT_in[],int size) from your comments it sounds like you are coding routine that is called as DLL or as part of a static library.
If this is the case then adding main() isn't going to help, at all.
What you have written is ABSOLUTELY 100% OK, if it is to be used as a callable routine.
What you might need to do is compile this routine into a library, even a static lib. is probably ok. If this is the case then consult your GCC documentation on how to create a static or dynamic lib.
Finally, I have written Verilog code myself, so you can also provide any lines or references to Verilog documentation that you have read and whose instructions you are following. I assume that at some point you are invoking Verilog and supplying it with a list of libraries it can/should use. Your lib should be included in that list.
Am including comments from jxh per his request:
To import the function into SystemVerilog, you need to compile your function into a shared object. Then, you would point SystemVerilog at the shared object. (I don't use SystemVerilog, but that is what I gather from its web page.)
gcc -shared -fPIC -g -Wall -Werror \
-I/home/ss69/fftw/local/include -L/home/ss69/fftw/local/lib \
fftw_test_DPI.c -lfftw3 -lm -o libfftw_test_DPI.so
Your are missing #include "svdpi.h" in the fftwc.c file (or maybe you are not showing it because it is in fftwc.h). This include is needed for DPI.
You are compiling a DPI library to be used with a SystemVerilog simulator. Therefore, you do not need a main() method.
I prefer to always compile all DPI methods outside of the SystemVerilog compiler. The include the DPI library to the simulation phase. My flow looks something like the following:
${SVTOOL} -compile -f svfiles.f -dpi_header gen_dpi_header.h
gcc -fPIC -pipe -O2 -c -g \
-I${SVTOOL_PATH}/include -Imy_dpi_dir -I. \
-o fftw_test_DPI.o \
fftw_test_DPI.c
gcc -shared -o libdpi.so \
fftw_test_DPI.o [other object files]
# then call ${SVTOOL} again for simulation with libdpi.so
If you cannot get past the first gcc stage then your issue is clearly on the C side.
I do not have access to the fftw3 library at the moment. I'm wondering your void fftw(double FFT_in[],int size) might be clobbering a library function. Try renaming it void dpi_fftw(double FFT_in[],int size)
You have no main function. Every binary must define main. If it doesn't, you don't have a null region of memory that _start defines in the binary, which means your program can't start!
Add a function:
int main(){
fftw(doubleArgumentsArray, intArgument); //Or whatever function calls this function
return 1; //Needed for C89, C99 will automatically return 1
}
Have found the following tutorial on Dynamic Programming Interface (DPI) :
http://www.doulos.com/knowhow/sysverilog/tutorial/dpi/
Specifically, scroll down to the "Including Foreign Language Code".
It should help with background information about how to construct a C modules for SystemVerilog.
Also, the tutorial has the following import statement:
import "DPI" function void slave_write(input int address, input int data);
This SystemVerilog statement obviously has input defs on the parameters, is this required? Your import does NOT identify input vs. output??
I believe this is an issue with some gcc linkers. I added the following linker flag:
irun ... -Wld,-B/usr/lib/x86_64-linux-gnu
And it fixed the issue.

Resources