Macro defined in main.c not visible in another included file - c

I have multiple C and H files
In main.c I defined a macro, and in ws_driver.c I want to use it.
ws_driver.h is included in main.c.
main.c
#define WS_PORT PORT_D8
#define WS_BIT D8
#define WS_DDR DDR_D8
#include "ws_driver.h"
In ws_dirver.c I have two checks:
ws_driver.c
#include "ws_driver.h"
#ifndef WS_PORT
# error "WS_PORT not defined!"
#endif
#ifndef WS_BIT
# error "WS_BIT not defined!"
#endif
Both are failing.
$ avr-gcc -std=gnu99 -mmcu=atmega328p -DF_CPU=16000000UL -Os -I. -I -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wno-main -Wno-strict-prototypes -Wno-comment -g2 -ggdb -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax -std=gnu99 main.c ws_driver.c --output main.elf
ws_driver.c:10:3: error: #error "WS_PORT not defined!"
# error "WS_PORT not defined!"
^
ws_driver.c:14:3: error: #error "WS_BIT not defined!"
# error "WS_BIT not defined!"
^
ws_driver.c: In function 'ws_show':
ws_driver.c:23:20: error: 'WS_PORT' undeclared (first use in this function)
#define bus_low() (WS_PORT) &= ~(1 << WS_BIT)
^
ws_driver.c:37:2: note: in expansion of macro 'bus_low'
bus_low();
^
ws_driver.c:23:20: note: each undeclared identifier is reported only once for each function it appears in
#define b......
What am I doing wrong? Please ask if you want to see some other part of the code.

You have to define the macros in a header file, not in the .c file if you want to use them in multiple places.
When the compiler compiles ws_driver.c it only includes ws_driver.h and the macro is not there. It does not include main.c. Each .c file is compiled separately.
Move the macro definitions in say config.h and include it everywhere you need it.
You can also use the compiler's define -DWS_BIT=123 -DOTHER=SMTH. The value you pass will be in the generated object file and can not be changed without recompiling.
If you want to compile only once, then pass these as parameters or create a configure_my_library() function...

Related

Macro wrongly defined in Makefile of Openwrt package

In the openwrt package that I'm working on, I defined a new config flag by adding following bloc to the Config.in file:
config VENDOR_PREFIX
string "Vendor Prefix"
default "X_Custom_SE_"
The flag is well added in the menuconfig:
I want that the value of this config flag is viewed in my C code as a macro. So I defined a macro CUSTOM_PREFIX in the Makefile of the package and assigned to it the value of the defined flag with this way:
TARGET_CFLAGS += -DCUSTOM_PREFIX=\"$(CONFIG_VENDOR_PREFIX)\"
and then I tried to use my macro in my C code by calling it in a structure variable initiation like that:
struct parameter_struct param1= {CUSTOM_PREFIX"param1", 4};
After that I tried to compile it. But I got this compilation error:
/home/user/openwrt//staging_dir/toolchain-mips_mips32_gcc-5.5.0_musl/usr/include -I/home/user/openwrt/staging_dir/toolchain-mips_mips32_gcc-5.5.0_musl/include/fortify -I/home/user/openwrt/staging_dir/toolchain-mips_mips32_gcc-5.5.0_musl/include -I/home/user/openwrt/staging_dir/target-mips_mips32_musl/usr/include -I/home/user/openwrt/staging_dir/target-mips_mips32_musl/usr/include -I/home/user/openwrt/staging_dir/target-mips_mips32_musl/usr/include -DCWMP_VERSION=\"3.0.0\" -I../inc/ -I../dm/ -I../dm/dmtree/ -I../dm/dmtree/common -I../dm/dmtree/tr098 -I../dm/dmtree/tr181 -I../dm/dmtree/upnp -Os -pipe -mips32 -mtune=mips32 -fno-caller-saves -DCONFIG_TARGET_iopsys_brcm63xx_mips -g3 -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -msoft-float -iremap/home/user/openwrt/build_dir/target-mips_mips32_musl/icwmp-curl/icwmp-4.0-2018-03-21:icwmp-4.0-2018-03-21 -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -DCUSTOM_PREFIX=X_CUSTOM1_SE_ -D_GNU_SOURCE -D_AADJ -MT ../dm/dmtree/common/libdatamodel_la-deviceinfo.lo -MD -MP -MF ../dm/dmtree/common/.deps/libdatamodel_la-deviceinfo.Tpo -c ../dm/dmtree/common/deviceinfo.c -fPIC -DPIC -o ../dm/dmtree/common/.libs/libdatamodel_la-deviceinfo.o
^
../dm/dmtree/common/deviceinfo.c: At top level:
<command-line>:0:15: error: 'X_CUSTOM1_SE_' undeclared here (not in a function)
../dm/dmtree/common/deviceinfo.c:28:2: note: in expansion of macro 'CUSTOM_PREFIX'
{CUSTOM_PREFIX"param1", 4}
struct parameter_struct param1= {CUSTOM_PREFIX"param1", 4};
seems like that the c program doesn't accept it as a string.
Is there something wrong in my macro definition?
As I expected and I noted in the my post title the mistake is in the definition of the macro in the Makefile. In Openwrt Makefile the definition of the Macro should be like that:
TARGET_CFLAGS += -DCUSTOM_PREFIX=\\\"$(CONFIG_VENDOR_PREFIX)\\\"

Error when including the same file in 2 files and then including them in another file (in c)

i have a problem in C which i don't know how to solve.
Suppuse i have 4 c files, a.c ; b.c ; c.c ; d.c,
and for each one of them there is an .h file: a.h ; b.h ; c.h ; d.h, which of course they include.
I want to do the following:
a.h will contain:
#include "b.h"
#include "c.h"
...
b.h will contain:
#include "d.h"
...
and c.h will also contain:
#include "d.h"
...
In d.h I define a struct, for example, the content of d.h will be:
typedef struct address {
int address;
} address;
The problem is that i get the error (when i compile the files):
In file included from c.h:1:0,
from a.h:2,
from a.c:1:
d.h:3:16: error: redefinition of ‘struct address’
d.h:3:16: note: originally defined here
d.h:5:3: error: conflicting types for ‘address’
d.h:5:3: note: previous declaration of ‘address’ was here
I understand why is it happening (because the preproccesor import the definition twice), but how do i solve it? I need the includes to be that's way (because of course i have more files, this was just an example). What can i do?
note: my makefile was:
project: a.o b.o c.o d.o
gcc -g a.o b.o c.o d.o -ansi -Wall -pedantic -o output
a.o: a.c a.h b.c b.h c.c c.h d.c d.h
gcc -c a.c -ansi -Wall -pedantic -o a.o
b.o: b.c b.h d.c d.h
gcc -c b.c -ansi -Wall -pedantic -o b.o
c.o: c.c c.h d.c d.h
gcc -c c.c -ansi -Wall -pedantic -o c.o
d.o: d.c d.h
gcc -c d.c -ansi -Wall -pedantic -o d.o
and i think it's okay.. It workd for me.
Thank you for the help.
Enclose the content of each header file in preprocessor guards:
/* a.h */
#ifndef A_H_
#define A_H_
/* content of a.h goes here */
#endif
Same for the other headers:
/* b.h */
#ifndef B_H_
#define B_H_
/* content of b.h goes here */
#endif
and so on.
That's the usual way to ensure that each header content is read only once. (When the file is read for the first time, the symbol [e.g. B_H_] has not yet been defined, so ifndef is true, and the content is read. From the second time on, the symbol is defined, and the content is skipped.)
Note that the name of the symbol A_H_ is arbitrary, but usually people use the name of the header written in capital letters. Hence the mechanism fails as soon as you include two different headers with the same name, unless you use different names for the guards.
You may also want to google for #pragma once, which many preprocessors support, but which is not standard.
You can use "includeguards" to prevent the preprocessor from putting the contents of header-files multiple times into your preprocessed source-code.
Using
#ifndef A_H_
#define A_H_
you define a symbol called A_H_. If the preprocessor hits this symbol another time, it will ignore what is between
#ifndef A_H_
#define A_H_
and
#endif
There are also specific compiler-commands like #pragma once, this works with Visual Studio for example and does the same as the include-guards do. Check if your compiler provides such things.
Add Once-Only Headers. Refer the below link for more information.
http://gcc.gnu.org/onlinedocs/cpp/Once_002dOnly-Headers.html#Once_002dOnly-Headers

Can't find a unistd.h with uuid_t typedef

Trying to build vSphere Perl SDK on Centos 2.6. Got all dependencies except one, namely UUID-0.05.
The problem seems to be that the uuid.h include file references unistd.h for the definition of uuid_t, but unistd.h has no such thing. Worse, though some people have described a conflict between the two include files for the variable, I cannot find a unistd.h file on the Internet with the definition.
Can someone point to such a unistd.h file? Or, even, a better approach to take?
Here's some info about the original issue:
In Changelog for uuid.1.6.2:
o Apply workaround to uuid.h to avoid conflicts with
vendor UUID implementations where uuid_t (Darwin/MacOSX)
or uuid_create/uuid_compare (POSIX) might exist.
[Ralf S. Engelschall]
In uuid.h:
/* workaround conflicts with system headers */
#define uuid_t __vendor_uuid_t
#define uuid_create __vendor_uuid_create
#define uuid_compare __vendor_uuid_compare
#include <sys/types.h>
#include <unistd.h>
#undef uuid_t
#undef uuid_create
#undef uuid_compare
Here's the original problem (compiling):
jloiacon#flowviewerprime /home/jloiacon/UUID-0.05 249 >make
cp UUID.pm blib/lib/UUID.pm
/usr/bin/perl /usr/share/perl5/ExtUtils/xsubpp -typemap /usr/share/perl5/ExtUtils/typemap UUID.xs > UUID.xsc && mv UUID.xsc UUID.c
gcc -c -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -DVERSION=\"0.05\" -DXS_VERSION=\"0.05\" -fPIC "-I/usr/lib64/perl5/CORE" UUID.c
UUID.xs: In function âdo_generateâ:
UUID.xs:13: error: storage size of âuuidâ isnât known
UUID.xs:14: warning: implicit declaration of function âuuid_generateâ
UUID.xs:13: warning: unused variable âuuidâ
UUID.xs: In function âdo_unparseâ:
UUID.xs:20: error: storage size of âuuidâ isnât known
UUID.xs:23: warning: implicit declaration of function âuuid_unparseâ
UUID.xs:20: warning: unused variable âuuidâ
UUID.xs: In function âdo_parseâ:
UUID.xs:29: error: storage size of âuuidâ isnât known
UUID.xs:33: warning: implicit declaration of function âuuid_parseâ
UUID.xs:30: warning: unused variable âstrâ
UUID.xs:29: warning: unused variable âuuidâ
make: *** [UUID.o] Error 1
Thanks
Install uuid-c++-devel.
lorem ipsum

Error: could not insert module. Unknown symbol in module

I'm trying to port RR0D Rasta Ring0 Debugger from 32-bit Linux to 64-bit Linux. I have converted 32-bit gcc inline assembly to 64-bit using vim regex as mentioned in my question: How to convert Linux 32-bit gcc inline assembly to 64-bit code?
I'm using gcc with -m64 flag. The target environment is Linux x86-64, custom kernel version 3.5.5.
The Makefile is the following:
EXTRA_CFLAGS += -O2 -Wall -DLINUX_26 -m64
OBJ := module_nux.o breakpoint.o buffering.o command.o disasmbak.o idt.o
OBJ += keyboard.o page.o video.o utils.o import_symb.o core_rr0d.o pci.o
MODULE := rr0d.o
obj-m := $(MODULE)
rr0d-objs := $(OBJ)
default:
make -C /lib/modules/`uname -r`/build/ SUBDIRS=`pwd` modules
clean:
rm -f *.o .*.o.cmd .*.ko.cmd *.mod.c *~
rm -rf .tmp_versions
mrproper:
make clean
rm -f *.ko
make gives a lot of warnings like warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] and warning: cast from pointer to integer of different size [-Wpointer-to-int-cast], but these are probably irrelevant to the topic.
The last rows of the output of make are probably the important ones:
/home/user/code/rr0d/0.3/core_rr0d.c: In function ‘cleanup_rr0d’:
/home/user/code/rr0d/0.3/core_rr0d.c:1938:36: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
CC [M] /home/user/code/rr0d/0.3/pci.o
LD [M] /home/user/code/rr0d/0.3/rr0d.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: "RING_HOOO_SEGMENT" [/home/user/code/rr0d/0.3/rr0d.ko] undefined!
CC /home/user/code/rr0d/0.3/rr0d.mod.o
LD [M] /home/user/code/rr0d/0.3/rr0d.ko
make[1]: Leaving directory `/home/user/code/kernel/linux-3.5.5'
So, RING_HOOO_SEGMENT is undefined.
When I try to insmod the module with insmod ./rr0d.ko as root, I get:
Error: could not insert module ./rr0d.ko: Unknown symbol in module
Checking with dmesg | tail -n 1 gives the following output:
[15975.412346] rr0d: Unknown symbol RING_HOOO_SEGMENT (err 0)
So, the unknown symbol definitively is RING_HOOO_SEGMENT.
RING_HOOO_SEGMENT is a constant created with #define in vars.h, that is included in several .c files with #include "vars.h".
The essential #ifdef block of vars.h with #define RING_HOOO_SEGMENT is this one:
#ifdef LINUX_26
#define fake_naked
#if defined(__GNUC__)
// the line below is the important one.
#define RING_HOOO_SEGMENT "$0x7b"
//#define RING_HOOO_SEGMENT "$0x60"
#elif defined(_MSC_VER)
#define RING_HOOO_SEGMENT 0x7b
#endif
#else /* LINUX_24 */
#define fake_naked _asm_("\t" \
"add $0x08, %esp\n\t" \
"popl %ebp\n" \
);
#if defined(__GNUC__)
#define RING_HOOO_SEGMENT "$0x18"
#elif defined(_MSC_VER)
#define RING_HOOO_SEGMENT 0x18
#endif
#define RING_HOOO_SEGMENT_VALUE 0x18
#endif /* LINUX_26 */
Obviously if #define RING_HOOO_SEGMENT "$0x7b" (in #if defined(__GNUC__) inside #ifdef LINUX_26) is commented out, the code won't compile, so it's clear that RING_HOOO_SEGMENT gets defined.
Grepping for RING_HOOO_SEGMENT gives the following matches:
$ grep 'RING_HOOO_SEGMENT' *.c *.o *.ko
core_rr0d.c: "movq RING_HOOO_SEGMENT, %rax\n\t"\
core_rr0d.c: __asm{ movq RING_HOOO_SEGMENT, %rax}\
Binary file rr0d.ko matches
Both core_rr0d.c rows are inline assembly. core_rr0d.c contains #include "vars.h" so that should be fine.
Also the binary module rr0d.ko matches, so it contains the string RING_HOOO_SEGMENT (in some form), even if insmod ./rr0d.ko fails with Error: could not insert module ./rr0d.ko: Unknown symbol in module.
Any ideas what might the reason for this problem and how to proceed to be able to insmod the module?
core_rr0d.c: "movq RING_HOOO_SEGMENT, %rax\n\t"\
Here RING_HOOO_SEGMENT is in a string (probably part of an inline assembler block). As such, the preprocessor will not substitute RING_HOOO_SEGMENT, and it gets passed as-is to the assembler, where the definition of RING_HOOO_SEGMENT is not available.
Fortunately, RING_HOOO_SEGMENT is itself defined as the string "$0x7b", so we can use compile-time string concatenation:
"movq " RING_HOOO_SEGMENT ", %rax\n\t"\
The preprocessor will substitute RING_HOOO_SEGMENT for "$0x7b", then GCC will concatenate these strings before passing it down to the assembler.

Howto resolve a function name conflict when compiling a kernel module

I'm trying to compile a 3rd party kernel module for RHEL 5.6 and it is failing due to function name conflicts with mutex_acquire and mutex_release. This kernel module compiles cleanly on RHEL 4.7 so something changed between kernels 2.6.9 and 2.6.18. Sadly, this kernel module is no longer supported by the vendor but I do have the source code for mutex.c and mutex.h which define these functions. Unfortunately there is an object file nivxi.o upon which no source code is distributed and this object file is calling mutex_acquire and mutex_release so I cannot just simply alter their names.
As an aside, I originally attempted to just modify the names slightly and the compile errors went away but when it went to make the .ko kernel module it complained that it couldn't find mutex_acquire or mutex_release; presumably due to nivxi.o
How do I force the compiler/linker to use the function definitions in my local .c/.h files even though they trounce over like-named functions elsewhere?
mutex.h
NIVXICC void mutex_acquire(mutex_t *mutex);
NIVXICC void mutex_release(mutex_t *mutex);
nivxicc.h (just incase this is pertinent)
#ifndef NIVXICC_H
#define NIVXICC_H
#define NIVXICC __attribute__((regparm(0))) __attribute__((cdecl))
#endif
/usr/include/lockdep.h (conflicting definition)
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# ifdef CONFIG_PROVE_LOCKING
# define mutex_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, i)
# else
# define mutex_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, i)
# endif
# define mutex_release(l, n, i) lock_release(l, n, i)
#else
# define mutex_acquire(l, s, t, i) do { } while (0)
# define mutex_release(l, n, i) do { } while (0)
#endif
Error
# make
make -C /lib/modules/2.6.18-238.el5/build SUBDIRS=/usr/local/nivxi/src KBUILD_VERBOSE=1 modules
make[1]: Entering directory `/usr/src/kernels/2.6.18-238.el5-i686'
test -e include/linux/autoconf.h -a -e include/config/auto.conf || ( \
echo; \
echo " ERROR: Kernel configuration is invalid."; \
echo " include/linux/autoconf.h or include/config/auto.conf are missing."; \
echo " Run 'make oldconfig && make prepare' on kernel src to fix it."; \
echo; \
/bin/false)
mkdir -p /usr/local/nivxi/src/.tmp_versions
rm -f /usr/local/nivxi/src/.tmp_versions/*
make -f scripts/Makefile.build obj=/usr/local/nivxi/src
gcc -m32 -Wp,-MD,/usr/local/nivxi/src/.vxi.o.d -nostdinc -isystem \
/usr/lib/gcc/i386-redhat-linux/4.1.2/include -D__KERNEL__ -Iinclude \
-include include/linux/autoconf.h -Wall -Wundef -Wstrict-prototypes \
-Wno-trigraphs -fno-strict-aliasing -fno-common -Wstrict-prototypes \
-Wundef -Werror-implicit-function-declaration \
-fno-delete-null-pointer-checks -fwrapv -Os -pipe -msoft-float \
-fno-builtin-sprintf -fno-builtin-log2 -fno-builtin-puts \
-mpreferred-stack-boundary=2 -march=i686 -mtune=generic -mtune=generic \
-mregparm=3 -ffreestanding -Iinclude/asm-i386/mach-generic \
-Iinclude/asm-i386/mach-default -fomit-frame-pointer -g -fno-stack-protector \
-Wdeclaration-after-statement -Wno-pointer-sign -DVXI_MAJOR=0 \
-DREMAP_PAGE_RANGE_VMA -D__DEBUG__ -DMODULE -D"KBUILD_STR(s)=#s" \
-D"KBUILD_BASENAME=KBUILD_STR(vxi)" -D"KBUILD_MODNAME=KBUILD_STR(vximod)" \
-c -o /usr/local/nivxi/src/.tmp_vxi.o /usr/local/nivxi/src/vxi.c
In file included from /usr/local/nivxi/src/vxi.c:13:
/usr/local/nivxi/src/mutex.h:59:42: error: macro "mutex_acquire" requires 4 arguments, but only 1 given
In file included from /usr/local/nivxi/src/vxi.c:13:
/usr/local/nivxi/src/mutex.h:59: warning: ‘regparm’ attribute only applies to function types
/usr/local/nivxi/src/mutex.h:59: warning: ‘cdecl’ attribute only applies to function types
/usr/local/nivxi/src/mutex.h:61:42: error: macro "mutex_release" requires 3 arguments, but only 1 given
/usr/local/nivxi/src/mutex.h:61: warning: ‘regparm’ attribute only applies to function types
/usr/local/nivxi/src/mutex.h:61: warning: ‘cdecl’ attribute only applies to function types
/usr/local/nivxi/src/vxi.c:128:31: error: macro "mutex_acquire" requires 4 arguments, but only 1 given
/usr/local/nivxi/src/vxi.c:133:31: error: macro "mutex_release" requires 3 arguments, but only 1 given
/usr/local/nivxi/src/vxi.c:146:31: error: macro "mutex_acquire" requires 4 arguments, but only 1 given
/usr/local/nivxi/src/vxi.c:158:31: error: macro "mutex_release" requires 3 arguments, but only 1 given
/usr/local/nivxi/src/vxi.c: In function ‘vxi_mmap’:
/usr/local/nivxi/src/vxi.c:243: error: implicit declaration of function ‘remap_page_range’
make[2]: *** [/usr/local/nivxi/src/vxi.o] Error 1
make[1]: *** [_module_/usr/local/nivxi/src] Error 2
make[1]: Leaving directory `/usr/src/kernels/2.6.18-238.el5-i686'
make: *** [default] Error 2
The problem will not be in your object file as macros have file-scope and are replaced by the preprocessor. Thus after being compiled, the macro no longer exists as far as your nivxi.o file is concerned.
The issue is probably in your mutex.h file. I would look at the top and you will likely see an #include <lockdep.h> line. Thus once the preprocessor gets down to your function definition, it treats mutex_acquire as a token to be replaced (with the wrong number of arguments).
The easiest way to solve your problem will be to #undef mutex_acquire and #undef mutex_release at the beginning of mutex.h. This will prevent the preprocessor from replacing the tokens in your mutex.h. Since defines have file-scope, you don't need to worry about this propagating beyond your application

Resources