I am using gcc compiler. I am working on a code that frequently involves writing chunks of statements inside a single #define directive. For example the following :
#include<stdio.h>
#define DO_RR(x) do { \
for(i=0;i<x; i++) \
printf("%d", i); \
}while(0);
int main() {
int i=0;
DO_RR(5)
return 0;
}
Now I want to be able to single step through the statements in DO_RR. However when I try it, the control jumps directly from DO_RR statement in main to the next statement and does not single step. Is there anyway to achieve stepping inside the preprocessor blocks ?
You cannot, #defines are expanded by the preprocessor and are not present in the code.
To supplement #Angelom's answer, you can workaround this by using functions. Move whatever code you can from the #define into a function, and you will be able to step through the function call.
Ideally, and most often, you can replace the entire #define with an inline function.
Related
I'm new to kernel development, and I need to write a Linux kernel module that performs several matrix multiplications (I'm working on an x64_64 platform). I'm trying to use fixed-point values for these operations, however during compilation, the compiler encounters this error:
error: SSE register return with SSE disabled
I don't know that much about SSE or this issue in particular, but from what i've found and according to most answers to questions about this problem, it is related to the usage of Floating-Point (FP) arithmetic in kernel space, which seems to be rarely a good idea (hence the utilization of Fixed-Point arithmetics). This error seems weird to me because I'm pretty sure I'm not using any FP values or operations, however it keeps popping up and in some ways that seem weird to me. For instance, I have this block of code:
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
const int scale = 16;
#define DOUBLE_TO_FIXED(x) ((x) * (1 << scale))
#define FIXED_TO_DOUBLE(x) ((x) / (1 << scale))
#define MULT(x, y) ((((x) >> 8) * ((y) >> 8)) >> 0)
#define DIV(x, y) (((x) << 8) / (y) << 8)
#define OUTPUT_ROWS 6
#define OUTPUT_COLUMNS 2
struct matrix {
int rows;
int cols;
double *data;
};
double outputlayer_weights[OUTPUT_ROWS * OUTPUT_COLUMNS] =
{
0.7977986, -0.77172316,
-0.43078753, 0.67738613,
-1.04312621, 1.0552227 ,
-0.32619684, 0.14119884,
-0.72325027, 0.64673559,
0.58467862, -0.06229197
};
...
void matmul (struct matrix *A, struct matrix *B, struct matrix *C) {
int i, j, k, a, b, sum, fixed_prod;
if (A->cols != B->rows) {
return;
}
for (i = 0; i < A->rows; i++) {
for (j = 0; j < B->cols; j++) {
sum = 0;
for (k = 0; k < A->cols; k++) {
a = DOUBLE_TO_FIXED(A->data[i * A->rows + k]);
b = DOUBLE_TO_FIXED(B->data[k * B->rows + j]);
fixed_prod = MULT(a, b);
sum += fixed_prod;
}
/* Commented the following line, causes error */
//C->data[i * C->rows + j] = sum;
}
}
}
...
static int __init insert_matmul_init (void)
{
printk(KERN_INFO "INSERTING MATMUL");
return 0;
}
static void __exit insert_matmul_exit (void)
{
printk(KERN_INFO "REMOVING MATMUL");
}
module_init (insert_matmul_init);
module_exit (insert_matmul_exit);
which compiles with no errors (I left out code that I found irrelevant to the problem). I have made sure to comment any error-prone lines to get to a point where the program can be compiled with no errors, and I am trying to solve each of them one by one. However, when uncommenting this line:
C->data[i * C->rows + j] = sum;
I get this error message in a previous (unmodified) line of code:
error: SSE register return with SSE disabled
sum += fixed_prod;
~~~~^~~~~~~~~~~~~
From what I understand, there are no FP operations taking place, at least in this section, so I need help figuring out what might be causing this error. Maybe my fixed-point implementation is flawed (I'm no expert in that matter either), or maybe I'm missing something obvious. Just in case, I have tested the same logic in a user-space program (using Floating-Point values) and it seems to work fine. In either case, any help in solving this issue would be appreciated. Thanks in advance!
Edit: I have included the definition of matrix and an example matrix. I have been using the default kbuild command for building external modules, here is what my Makefile looks like:
obj-m = matrix_mult.o
KVERSION = $(shell uname -r)
all:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
Linux compiles kernel code with -mgeneral-regs-only on x86, which produces this error in functions that do anything with FP or SIMD. (Except via inline asm, because then the compiler doesn't see the FP instructions, only the assembler does.)
From what I understand, there are no FP operations taking place, at least in this section, so I need help figuring out what might be causing this error.
GCC optimizes whole functions when optimization is enabled, and you are using FP inside that function. You're doing FP multiply and truncating conversion to integer with your macro and assigning the result to an int, since the MCVE you eventually provided shows struct matrix containing double *data.
If you stop the compiler from using FP instructions (like Linux does by building with -mgeneral-regs-only), it refuses to compile your file instead of doing software floating-point.
The only odd thing is that it pins down the error to an integer += instead of one of the statements that compiles to a mulsd and cvttsd2si
If you disable optimization (-O0 -mgeneral-regs-only) you get a more obvious location for the same error (https://godbolt.org/z/Tv5nG6nd4):
<source>: In function 'void matmul(matrix*, matrix*, matrix*)':
<source>:9:33: error: SSE register return with SSE disabled
9 | #define DOUBLE_TO_FIXED(x) ((x) * (1 << scale))
| ~~~~~^~~~~~~~~~~~~~~
<source>:46:21: note: in expansion of macro 'DOUBLE_TO_FIXED'
46 | a = DOUBLE_TO_FIXED(A->data[i * A->rows + k]);
| ^~~~~~~~~~~~~~~
If you really want to know what's going on with the GCC internals, you could dig into it with -fdump-tree-... options, e.g. on the Godbolt compiler explorer there's a dropdown for GCC Tree / RTL output that would let you look at the GIMPLE or RTL internal representation of your function's logic after various analyzer passes.
But if you just want to know whether there's a way to make this function work, no obviously not, unless you compile a file without -mgeneral-registers-only. All functions in a file compiled that way must only be called by callers that have used kernel_fpu_begin() before the call. (and kernel_fpu_end after).
You can't safely use kernel_fpu_begin inside a function compiled to allow it to use SSE / x87 registers; it might already have corrupted user-space FPU state before calling the function, after optimization. The symptom of getting this wrong is not a fault, it's corrupting user-space state, so don't assume that happens to work = correct. Also, depending on how GCC optimizes, the code-gen might be fine with your version, but might be broken with earlier or later GCC or clang versions. I somewhat expect that kernel_fpu_begin() at the top of this function would get called before the compiler did anything with FP instructions, but that doesn't mean it would be safe and correct.
See also Generate and optimize FP / SIMD code in the Linux Kernel on files which contains kernel_fpu_begin()?
Apparently -msse2 overrides -mgeneral-regs-only, so that's probably just an alias for -mno-mmx -mno-sse and whatever options disables x87. So you might be able to use __attribute__((target("sse2"))) on a function without changing build options for it, but that would be x86-specific. Of course, so is -mgeneral-regs-only. And there isn't a -mno-general-regs-only option to override the kernel's normal CFLAGS.
I don't have a specific suggestion for the best way to set up a build option if you really do think it's worth using kernel_fpu_begin at all, here (rather than using fixed-point the whole way through).
Obviously if you do save/restore the FPU state, you might as well use it for the loop instead of using FP to convert to fixed-point and back.
I have a bunch of macros to define with same prefix and I don't want to define them one by one.
Say, I want to define like:
static constexpr str_1 = "str_1";
static constexpr str_2 = "str_2";
....
static constexpr str_100 = "str_100";
I tried:
#define DECLARE_STR(variable_prefix, val_prefix, cur, max) do { \
if ((cur) < (max)) { \
static constexpr variable_prefix##cur = val_prefix#cur; \
DECLARE_STR(variable_prefix, val_prefix, cur+1 , max) \
} while(0)
But got errors: error: expected member name or ';' after declaration specifiers
Do I have a correct way to implement this?
There are two problems with your code.
First, the do/while(0) construct is useful to ensure that macros expand to a single statement. What you want to generate are variable definitions at the global namespace, for which statements are unsuited: just remove the do/while(0). The if won't be able to do anything about declaring variables either, it can only branch at runtime on values. But in any case...
The other issue is that you're trying to call the macro recursively. The C++ preprocessor is not able to perform such recursion: a macro cannot be expanded within its own expansion. Working around that requires a lot of boilerplate to generate iteration sequences up to a limit. Fortunately(?), Boost.Preprocessor has the boilerplate already done:
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/stringize.hpp>
#define DECLARE_ONE_STR(z, n, data) \
static constexpr BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(0, data), n) = BOOST_PP_TUPLE_ELEM(1, data) BOOST_PP_STRINGIZE(n);
#define DECLARE_STR(variable_prefix, val_prefix, max) \
BOOST_PP_REPEAT(max, DECLARE_ONE_STR, (variable_prefix, val_prefix))
See it live on Coliru
I'm using Codeblocks 13.12 with MinGW on Winodows 10. I'm somewhat familiar with C, but haven't been coding for some while. Last time I wrote a code was with Turbo compiler. So I'm starting to code once again and this the first time I'm using GCC. So I thought of starting with a simple code to print the pattern:Pattern to print
The code I wrote is:
#include<stdio.h>
using namespace std;
int main()
{
int i=0,j=0,k=0;
for(i;i<=4;++i)
{
j=2*i+1;
for(k=1;k<=j;++k)
printf(k);
}
return 0;
}
The error I get is:Error on build attempt
Tell me, is it because of some error in my code(not logical), or there's something else.
first of all there is no space after the include.
EDIT: Tried it, and it works with no space, but it's better for further reading
second, using namespace is not C, it is C++,
third, the printf function has to look like this: printf("%i",k); there has to be placeholders for each variable you want to print. please see some turorial and don't mix C and C++. If you want to program in C++ use something like cout >> instead of printf and use the C++-Headers, #include <stdio>
That works and is good to read ;-):
#include <stdio.h>
int main()
{
int i=0,j=0,k=0;
for(i;i<=4;++i)
{
j=2*i+1;
for(k=1;k<=j;++k)
printf("%i\n",k);
}
return 0;
}
I'm using Klee 2.9, and trying to obtain branch information from stat file klee generats. I fed in a one if-else statement program, and klee reported NumBranches as 8.
Code under test is shown below,
#include <stdio.h>
#include <stdbool.h>
int main(){
int a;
int b;
klee_make_symbolic(&a,sizeof(a),"a");
klee_make_symbolic(&b,sizeof(b),"b");
if (a / b == 1) {
printf("a==b\n");
}
else {
printf("a!=b\n");
}
return 0;
}
and file output run.stats in shown below,
('Instructions','FullBranches','PartialBranches','NumBranches','UserTime','NumStates','MallocUsage','NumQueries','NumQueryConstructs','NumObjects','WallTime','CoveredInstructions','UncoveredInstructions','QueryTime','SolverTime','CexCacheTime','ForkTime','ResolveTime',)
(0,0,0,8,5.609000e-03,0,528704,0,0,0,4.196167e-05,0,78,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00)
(32,2,0,8,9.722000e-03,0,654176,3,56,0,3.826760e-01,27,51,3.799300e-01,3.802470e-01,3.801040e-01,6.900000e-05,0.000000e+00)
Can anyone explain me how does 8 come from?
Two possible reasons:
"klee_make_symbolic" and "printf" contains conditional statements. When KLEE executes the program, it does not differentiate your functions from external functions.
If you run KLEE with "--libc=uclibc", the main function will be replaced with "__uclibc_main". "__uclibc_main" first do some initialization works and then call the original "main" function. The initialization might contain some conditional statements.
You need to check the version of KLEE and the commands you used.
I'm trying to pass the value of a C macro to the preprocessor with the -Dmacro=value option of gcc. However, it doesn't do what i expect. This is the basics of my code:
#define T0 0
#define T1 0
#define T2 0
#define T3 0
int main(){
int f[9];
start(f[T0], f[T1], f[T2], f[T3]);
return 0;
}
Running gcc -DT3=1 -E shows the preprocessor does not replace the original value of T3. What am i missing, and how can the value be passed properly?
Afaik that switch will define a macro, but your code then overrides it back to 0. Remove that define from your code or surround it with ifdef and it should be fine.