why am i geting an undefined reference linking error in C - c

I'm doing some experiments with the nRF52840 and SEGGER Embedded Studio. I'm quite new to C but managed to get desired results using and changing the examples. I'm now trying to port the uart example to the two way ranging example to send the results to an external device but keep running into the following error:
I pinpointed the error (I think at least) to the following piece of code in a file named app_uart.h the problematic functions gets called in the second last line of the following code block:
uint32_t app_uart_init(const app_uart_comm_params_t * p_comm_params,
app_uart_buffers_t * p_buffers,
app_uart_event_handler_t error_handler,
app_irq_priority_t irq_priority);
// TODO no reference to app_uart_init()
#define APP_UART_FIFO_INIT(P_COMM_PARAMS, RX_BUF_SIZE, TX_BUF_SIZE, EVT_HANDLER, IRQ_PRIO, ERR_CODE) \
do \
{ \
app_uart_buffers_t buffers; \
static uint8_t rx_buf[RX_BUF_SIZE]; \
static uint8_t tx_buf[TX_BUF_SIZE]; \
\
buffers.rx_buf = rx_buf; \
buffers.rx_buf_size = sizeof (rx_buf); \
buffers.tx_buf = tx_buf; \
buffers.tx_buf_size = sizeof (tx_buf); \
ERR_CODE = app_uart_init(P_COMM_PARAMS, &buffers, EVT_HANDLER, IRQ_PRIO); \
} while (0)
The error is, according to SEGGER Embedded Studio, in my ds_twr_responder.c file pointing to the function call
APP_UART_FIFO_INIT(&com_params, UART_RX_BUFF_SIZE, UART_TX_BUFF_SIZE, uart_err_handle, APP_IRQ_PRIORITY_LOWEST, err_code);
going to the declaration of the function brigs us to app_uart.h. this file is in de same directory as ds_twr_responder.c along with app_uart.c (in which the function is defined)
I don't really kno where to look as i'm not sure why this error could possibly pop up.
Is there some direction i should be looking in?

Related

What is Significance of _v(l) in the macro?

I am trying to understand the following macro from the following URL:
do { \
word _v(l) = vec_len (V); \
V = _vec_resize ((V), 1, (_v(l) + 1) * sizeof ((V)[0]), (H), (A)); \
(V)[_v(l)] = (E); \
} while (0)
what is the significance of _v(l)? Is it just a variable or something more?
The _v macro is defined in vec.h at line 207:
#define _v(var) _vec_##var
This prepends _vec_ before var. You can observe this by asking your favorite compiler to print the output of the preprocessor stage (-E flag for clang/gcc and /E for msvc).
#define _v(var) _vec_##var
word _v(l) = vec_len (V);
Is expanded into:
word _vec_l = vec_len (V);
It is a variable whose name is generated. The name probably includes the current line number to make it unique. Therefore using this macro twice in a line may or may not work.
To see what the macro expands to, run gcc -E to only preprocess the code but not compile it. Do a bit of research about this -E computer option, it is helpful in many similar cases as well.

Why I get just one section when I use __EXPORT_SYMBOL

As we know ,__EXPORT_SYMBOL is used when we want to export our symbols .
I found there is a macro in
exort.h
As you can see it below:
#ifdef CONFIG_MODVERSIONS
/* Mark the CRC weak since genksyms apparently decides not to
* generate a checksums for some symbols */
#define __CRC_SYMBOL(sym, sec) \
extern void *__crc_##sym __attribute__((weak)); \
static const unsigned long __kcrctab_##sym \
__used \
__attribute__((section("___kcrctab" sec "+" #sym), unused)) \
= (unsigned long) &__crc_##sym;
#else
#define __CRC_SYMBOL(sym, sec)
#endif
There is a line: "attribute((section("_kcrctab" sec "+" #sym), unused))"
I believe it means that this variable(unsigned long _kcrctab##sym) will be placed in a special section ,whose name is ("_kcrctab" sec "+" #sym).Doesn't it mean there would be a lot of sections in the final elf file?
But,I use readelf utility to check vmlinux and I found there is only one section.
__kcrctab_gpl.It's size is 0x3F40 .
Could you please help me. I am a new comer.
They get mapped back into .rodata by the linker script.
From the arm version: ./arch/arm/kernel/vmlinux.lds
__kcrctab : AT(ADDR(__kcrctab) - 0) {
__start___kcrctab = .;
*(SORT(___kcrctab+*)) __stop___kcrctab = .;
}
There are a lot of things going on in those linker scripts, but the basic idea here is that everything which lives in a '__kcrctab+*' section gets put into __kcrctab.

System string2.h header file generates a compilation error when optimizing

I am running Linaro Ubuntu 12.03 on an embedded platform. After using this system for a few months for building a simple program, I started receiving a compilation error when adding an optimization option. So, I created a test program:
// test.c
#include <string.h>
int main(int argc, char *argv[])
{
return 0;
}
compiling with:
gcc test.c
works just fine. However, when I add an optimization option:
gcc -O1 test.c
I get an error:
In file included from /usr/include/string.h:637:0,
from test.c:1:
/usr/include/arm-linux-gnueabi/bits/string2.h:1305:3: error: "(" may not appear in macro parameter list
This happens for all levels from -O1 to -Ofast.
Trying the same on another embedded system with Linaro Ubuntu 12.04, it works just fine. So does it on my Ubuntu PC.
The code section in string2.h:
# define __strdup(sp \
(__extension__ (__builtin_constant_p (s) && __string2_1bptr_p (s) \
? (((__const char *) (s))[0] == '\0' \
? (char *) calloc ((size_t) 1, (size_t) 1) \
: ({ size_t __len = strlen (s) + 1; \
char *__retval = (char *) malloc (__len); \
if (__retval != NULL) \
__retval = (char *) memcpy (__retval, s, __len); \
__retval; })) \
: __strdup (s)))
(the problem is in the 2nd line of the macro)
Why did my build environment stop working with no apparent reason?
UPDATE 1:
I just examined the same file on another board running 12.03, as well as the one on the 12.04 system. It looks like there is indeed a syntax error in the string2.h file on the 1st board. The two other files show:
# define __strdup(s) \
instead of:
# define __strdup(sp \
so it the ) was replaced with p. The only explanation I can think of now is that the SD card I am using starts to corrupt files. However, any other explanation is appreciated.
Since it used to work in the past and string2.h changed on the SD card, it's likely that there's a bad sector in the SD card at the least.

undefined reference to function declared in *.h file

I am a unskilled programmer and new to linux, I run into a problem when complining. I have two files 'ex_addinst.c' and 'lindo.h' in the same folder, I input command :
g++ -c ex_addinst.c
then, a object file ex_addinst.o is genetated with a warning:
ex_addinst.c: In function ‘int main()’:
ex_addinst.c:80: warning: deprecated conversion from string constant to ‘char*’
then I leak them with
g++ -Wall -o ex_addinst ex_addinst.o
and get the following info:
ex_addinst.o: In function `main':
ex_addinst.c:(.text+0x2b): undefined reference to `LSloadLicenseString'
ex_addinst.c:(.text+0x75): undefined reference to `LSgetVersionInfo'
ex_addinst.c:(.text+0xae): undefined reference to `LScreateEnv'
ex_addinst.c:(.text+0x10a): undefined reference to `LSgetErrorMessage'
...
...
ex_addinst.c:(.text+0x1163): undefined reference to `LSdeleteEnv'
collect2: ld returned 1 exit status
I guess that the header file 'lindo.h' is not complied into the .o file, but I have no idea what to do now. I have tried gcc, but get the same error. the version of my g++ and gcc is 4.4.5. I am using Ubuntu 10.10.
All the functions and structures have been declared in 'lindo.h'.
part of ex_addinst.c is as follows:
#include <stdio.h>
#include <stdlib.h>
/* LINDO API header file */
#include "lindo.h"
enter code here
int CALLTYPE LSwriteMPIFile(pLSmodel pModel,
char *pszFname);
/* Define a macro to declare variables for
error checking */
#define APIERRORSETUP \
int nErrorCode; \
char cErrorMessage[LS_MAX_ERROR_MESSAGE_LENGTH] \
/* Define a macro to do our error checking */
#define APIERRORCHECK \
if (nErrorCode) \
{ \
if ( pEnv) \
{ \
LSgetErrorMessage( pEnv, nErrorCode, \
cErrorMessage); \
printf("nErrorCode=%d: %s\n", nErrorCode, \
cErrorMessage); \
} else {\
printf( "Fatal Error\n"); \
} \
exit(1); \
} \
#define APIVERSION \
{\
char szVersion[255], szBuild[255];\
LSgetVersionInfo(szVersion,szBuild);\
printf("\nLINDO API Version %s built on %s\n",szVersion,szBuild);\
}\
/* main entry point */
int main()
{
APIERRORSETUP;
pLSenv pEnv;
pLSmodel pModel;
char MY_LICENSE_KEY[1024];
/*****************************************************************
* Step 1: Create a model in the environment.
*****************************************************************/
nErrorCode = LSloadLicenseString("home/li/work/tools/lindo/lindoapi/license/lndapi60.lic", MY_LICENSE_KEY);
if ( nErrorCode != LSERR_NO_ERROR)
{
printf( "Failed to load license key (error %d)\n",nErrorCode);
exit( 1);
}
......
......
......
APIERRORCHECK;
{
int nStatus;
double objval=0.0, primal[100];
/* Get the optimization result */
nErrorCode = LSgetInfo(pModel, LS_DINFO_GOP_OBJ, &objval);
APIERRORCHECK;
LSgetMIPPrimalSolution( pModel, primal) ;
APIERRORCHECK;
printf("\n\nObjective = %f \n",objval);
printf("x[0] = %f \n",primal[0]);
printf("x[1] = %f \n",primal[1]);
/* Get the linearity of the solved model */
nErrorCode = LSgetInfo (pModel, LS_IINFO_GOP_STATUS, &nStatus);
APIERRORCHECK;
/* Report the status of solution */
if (nStatus==LS_STATUS_OPTIMAL || nStatus==LS_STATUS_BASIC_OPTIMAL)
printf("\nSolution Status: Globally Optimal\n");
else if (nStatus==LS_STATUS_LOCAL_OPTIMAL)
printf("\nSolution Status: Locally Optimal\n\n");
else if (nStatus==LS_STATUS_INFEASIBLE)
printf("\nSolution Status: Infeasible\n\n");
}
/* >>> Step 7 <<< Delete the LINDO environment */
LSdeleteEnv(&pEnv);
/* Wait until user presses the Enter key */
printf("Press <Enter> ...");
getchar();
}
part of 'lindo.h' is:
/*********************************************************************
* Structure Creation and Deletion Routines (4) *
*********************************************************************/
pLSenv CALLTYPE LScreateEnv(int *pnErrorcode,
char *pszPassword);
pLSmodel CALLTYPE LScreateModel(pLSenv pEnv,
int *pnErrorcode);
int CALLTYPE LSdeleteEnv(pLSenv *pEnv);
int CALLTYPE LSdeleteModel(pLSmodel *pModel);
int CALLTYPE LSloadLicenseString(char *pszFname, char *pachLicense);
void CALLTYPE LSgetVersionInfo(char *pachVernum, char *pachBuildDate);
Thank you!
Thank you guys answering my problem. As you suggested, I need to link the library when complining. I have gotten the executable file with:
gcc -o ex_addinst ./ex_addinst.o -L/home/li/work/tools/lindo/lindoapi/bin/linux64 -m64 -llindo64 -lmosek64 -lconsub3 -lc -ldl -lm -lguide -lpthread -lsvml -limf -lirc
but there comes another problem when run the executable file ex_addinst: after run:
./ex_addinst
there comes:
./ex_addinst: error while loading shared libraries: liblindo64.so.6.0: cannot open shared object file: No such file or directory
The tricky thing is, liblindo64.so.6.0 is in the lib folder which contains:
libconsub3.so libirc.so liblindojni.so libmosek64.so.5.0 lindo.par
libguide.so liblindo64.so liblindojni.so.6.0.3 libsvml.so placeholder
libimf.so liblindo64.so.6.0 libmosek64.so lindoapivars.sh runlindo
I have created symbolic links between liblindo64.so.6.0 and liblindo64.so with
ln -sf liblindo64.so.6.0 liblindo64.so
but it doesn't help.
Can anyone tell me what is wrong here?
(I am not sure I should put this question in a new post, but I think currently it is better to follow the old one)
Ok, lindo.h contains the prototypes for those functions, but where are the functions actually defined? If they're in another C file you need to compile that one too, and link both the object files together.
If the functions are part of another static library, you need to tell the linker to link that library along with your object file.
If they're defined with a shared library, you can probably get g++ to still link to it at compile time, and take care of the library loading etc. Otherwise you'll need to load the library at runtime and reference the functions from the library. This Wikipedia article on dynamic loading of shared libraries contains some example code.
Try
g++ -Wall -o ex_addinst ex_addinst.c
instead of
g++ -Wall -o ex_addinst ex_addinst.o
You want to compile the .c file, not the .o file.
You need to tell gcc to link with the library or object file(s) that contain the LS... functions you're using. The header file tells the compiler how to call them, but the linker needs to know where to get the compiled code from.
undefined reference to ... is not a declaration problem. The compiler fails because it can't find symbols (objects) which are related to those declared functions.
In your case, you use the Limbo API, and include the header file, but you don't tell the compiler to link with the library : that's why it doesn't find symbols.
EDIT : I had forgotten the part when you say you're new to Linux. To link with the library, you need to use the -L/-l options of g++. man g++ is always a good read, and the Limbo's documentation should be, too.

Why are these C macros not written as functions?

I'm studying the code of the netstat tool (Linux), which AFAIK mostly reads a /proc/net/tcp file and dowa pretty-printing out of it. (My focus is on the -t mode right now.)
I'm a bit puzzled by the coding style the authors have chosen:
static int tcp_info(void)
{
INFO_GUTS6(_PATH_PROCNET_TCP, _PATH_PROCNET_TCP6, "AF INET (tcp)", tcp_do_one);
}
where
#define INFO_GUTS6(file,file6,name,proc) \
char buffer[8192]; \
int rc = 0; \
int lnr = 0; \
if (!flag_arg || flag_inet) { \
INFO_GUTS1(file,name,proc) \
} \
if (!flag_arg || flag_inet6) { \
INFO_GUTS2(file6,proc) \
} \
INFO_GUTS3
where
#define INFO_GUTS3 \
return rc;
and
#if HAVE_AFINET6
#define INFO_GUTS2(file,proc) \
lnr = 0; \
procinfo = fopen((file), "r"); \
if (procinfo != NULL) { \
do { \
if (fgets(buffer, sizeof(buffer), procinfo)) \
(proc)(lnr++, buffer); \
} while (!feof(procinfo)); \
fclose(procinfo); \
}
#else
#define INFO_GUTS2(file,proc)
#endif
etc.
Clearly, my coding sense is tilting and says "those should be functions". I don't see any benefit those macros bring here. It kills readability, etc.
Is anybody around familiar with this code, can shed some light on what "INFO_GUTS" is about here and whether there could have been (or still has) a reason for such an odd coding style?
In case you're curious about their use, the full dependency graph goes like this:
# /---> INFO_GUTS1 <---\
# INFO_GUTS --* INFO_GUTS2 <----*---- INFO_GUTS6
# î \---> INFO_GUTS3 <---/ î
# | |
# unix_info() igmp_info(), tcp_info(), udp_info(), raw_info()
Your sense that "those macros should be functions" seems correct to me; I'd prefer to see them as functions.
It would be interesting to know how often the macros are used. However, the more they're used, the more there should be a space saving if they're a real function instead of a macro. The macros are quite big and use (inherently slow) I/O functions themselves, so there isn't going to be a speed-up from using the macro.
And these days, if you want inline substitution of functions, you can use inline functions in C (as well as in C++).
You can also argue that INFO_GUTS2 should be using a straight-forward while loop instead of the do ... while loop; it would only need to check for EOF once if it was:
while (fgets(buffer, sizeof(buffer), procinfo))
(*proc)(lnr++, buffer);
As it is, if there is an error (as opposed to EOF) on the channel, the code would probably go into an infinite loop; the fgets() would fail, but the feof() would return false (because it hasn't reached EOF; it has encountered an error - see ferror()), and so the loop would continue. Not a particularly plausible problem; if the file opens, you will seldom get an error. But a possible problem.
There is no reason why. The person who wrote the code was likely very confused about code optimizations in general, and the concept of inlining in particular. Since the compiler is most likely GCC, there are several ways to achieve function inlining, if inlining was even necessary for this function, which I very much doubt.
Inlining a function containing file I/O calls would be the same thing as shaving an elephant to reduce its weight...
It reads as someones terrible idea to implement optional IPv6 support. You would have to walk through the history to confirm, but the archive only seems to go back to 1.46 and the implied damage is at 1.20+.
I found a git archive going back to 1.24 and it is still there. Older code looks doubtful.
Neither BusyBox or BSD code includes such messy code. So it appeared in the Linux version and suffered major bit rot.
Macros generate code: when it is called, the whole macro definition is expanded at the place of the call. If say, INFO_GUTS6 were a function, it wouldn't be able to declare, e.g., the buffer variable which would subsequently be usable by the code that follows the macro invocation. The example you pasted is actually very neat :-)

Resources