compiling linux 0.0.1 => error: ‘asm’ operand has impossible constraints __asm__("cld\n" - c

I'm trying to compile linux kernel 0.0.1 from source code on my 64 bit intel machine.
Only to fill in the boot and main I had to modify all makefiles to get a 32-bit compilation.
So, this is the output of make:
In file included from traps.c:7:0:
../include/string.h:128:22: warning: conflicting types for built-in function ‘strchr’
extern inline char * strchr(const char * s,char c)
^
../include/string.h:145:22: warning: conflicting types for built-in function ‘strrchr’
extern inline char * strrchr(const char * s,char c)
^
../include/string.h:379:22: warning: conflicting types for built-in function ‘memchr’
extern inline void * memchr(const void * cs,char c,int count)
^
../include/string.h:395:22: warning: conflicting types for built-in function ‘memset’
extern inline void * memset(void * s,char c,int count)
^
In file included from traps.c:11:0:
../include/linux/kernel.h:5:1: warning: function return types not compatible due to ‘volatile’
volatile void panic(const char * str);
^
../include/linux/kernel.h:5:1: warning: function return types not compatible due to ‘volatile’
../include/linux/kernel.h:5:1: warning: function return types not compatible due to ‘volatile’
In file included from traps.c:7:0:
../include/string.h: In function ‘strcpy’:
../include/string.h:29:1: error: ‘asm’ operand has impossible constraints
__asm__("cld\n"
^
Makefile:24: set di istruzioni per l'obiettivo "traps.o" non riuscito
The portion of code of string.h is the following:
extern inline char * strcpy(char * dest,const char *src)
{
__asm__("cld\n"
"1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
::"S" (src),"D" (dest):"si","di","ax");
return dest;
}
I don't know why the original code doesn't compile.
Until now I successfully compiled: boot and init subdir.
Many Thanks

I think that the problem is that the register clobber list overlaps with the inputs.
That is, the "S" stands for register esi while "D" stands for register edi; but then the clobber list contains "si" and "di" that are the lower 16 bit pieces of those registers. Maybe old GCC versions ignored that, but newer ones do not allow overlaps.
From the docs here:
Clobber descriptions may not in any way overlap with an input or output operand.
Solution, just remove them from the list:
...
::"S" (src),"D" (dest) :"ax", "cc");
BTW, I also added the clobber to "cc" because that assembly modifies the e flag.

Related

Why can I call my function with the wrong signature when using extern?

I have some example code. When I uncomment the invalid_call function call I get a compiler error as expected. Unfortunately, calling my_function with wrong number of arguments still compiles leading to undefined behavior (UB).
main.c
#include <linux/module.h>
#include <linux/kernel.h>
#include "header.h"
extern void my_function(int x);
static int my_init(void)
{
my_function(5);
// invalid_call( 5 ); // doesn't compile
return 0;
}
static void my_exit(void)
{
pr_info("removing module");
}
module_init(my_init);
module_exit(my_exit);
func_source.c
#include <linux/kernel.h>
void my_function(int x, int y)
{
pr_info("%d %d",x,y);
}
header.h
void invalid_call(int x, int y)
{
return;
}
Expected output:
Compiler error when calling my_function() with only one argument.
Actual output:
Code compiles and prints a random value for y, essentially UB.
I know that extern void my_function(int x); is just another declaration so I don't think compiler needs to throw an error however, when I call my_function with a single argument, it shouldn't be able to find a match to any function definition. Unfortunately, instead of a compiler error I run into UB.
How does this work? I know UB is UB but how why does it become UB. I thought the function signature mismatch would cause a compiler. My suspicion is the extern declaration but still...
Also, bonus question. How do I avoid running into this problem again? Any design patterns or practices I can follow?
Here is the Makefile if you want to test it out yourself.
obj-m += main.o
example-y := ./src/main.o ./src/func_src.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Folder structure:
./Makefile
./src/main.c
./src/my_func.c
Thanks in advance.
In C, at least, neither the compiler nor the linker has global knowledge of all the functions in all the source files of your program (or kernel module, or whatever). The compiler compiles one source file at a time, and all it has to go on is the declarations -- including the prototypes -- that are visible during that one compilation. So if the prototype is wrong -- you're doomed. The compiler validates your (incorrect) call against the (incorrect) prototype, and finds no mismatch, and so generates an (incorrect) call that passes one argument, leading to the behavior you see.
For this reason it's an excellent idea to:
never put external prototypes in .c files, but rather, in .h files, which you include wherever you call the functions, and
also include the .h file in the source file where you define the function.
That way, not only does the compiler check that the calls match the prototype, it can also check that the prototype matches the actual definition, and since there's only one copy of the prototype (in that one .h file), it's more or less impossible for it to fall out of sync and end up being incorrect. See also this question.
In your question, you seemed to think that it wouldn't even be possible for the incorrect call to be linked up with the two-argument-accepting definition. That might be true in C++, where "name mangling" arranges for a function's arguments to be part of its signature. But nothing like that happens in C. Your function's sole identity -- in the symbol table, and as far as the linker is concerned -- is the name my_function, and nothing at link time prevents a one-arg-passing call from being matched up with the two-arg-accepting definition.
Some ways to detect this problem:
building in gcc with link-time optimization will usually flag this.
Using -Wmissing-prototypes would have warned for func_source.c that you have an externally-visible function with no prototype.
You should have the correct prototype in a header file that is included by all units that want to call the function, as well as the unit containing the function definition. The latter warning flag will detect if you forget to put the prototype in the unit containing the definition (which would have caused a compilation error due to the prototype not matching the definition).
the OPs posted code results in the following messages from the compiler:
gcc -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled.c" (in directory: /home/richard/Documents/forum)
untitled.c: In function ‘invalid_call’:
untitled.c:1:23: warning: unused parameter ‘x’ [-Wunused-parameter]
void invalid_call(int x, int y)
^
untitled.c:1:30: warning: unused parameter ‘y’ [-Wunused-parameter]
void invalid_call(int x, int y)
^
untitled.c: In function ‘my_init’:
untitled.c:15:5: warning: implicit declaration of function ‘my_function’; did you mean ‘myFunction’? [-Wimplicit-function-declaration]
my_function(5);
^~~~~~~~~~~
myFunction
untitled.c: In function ‘my_exit’:
untitled.c:22:5: warning: implicit declaration of function ‘pr_info’ [-Wimplicit-function-declaration]
pr_info("removing module");
^~~~~~~
untitled.c: At top level:
untitled.c:25:1: warning: data definition has no type or storage class
module_init(my_init);
^~~~~~~~~~~
untitled.c:25:1: warning: type defaults to ‘int’ in declaration of ‘module_init’ [-Wimplicit-int]
untitled.c:25:1: warning: parameter names (without types) in function declaration
untitled.c:26:1: warning: data definition has no type or storage class
module_exit(my_exit);
^~~~~~~~~~~
untitled.c:26:1: warning: type defaults to ‘int’ in declaration of ‘module_exit’ [-Wimplicit-int]
untitled.c:26:1: warning: parameter names (without types) in function declaration
untitled.c:28:6: warning: conflicting types for ‘my_function’
void my_function(int x, int y)
^~~~~~~~~~~
untitled.c:15:5: note: previous implicit declaration of ‘my_function’ was here
my_function(5);
^~~~~~~~~~~
untitled.c:20:13: warning: ‘my_exit’ defined but not used [-Wunused-function]
static void my_exit(void)
^~~~~~~
untitled.c:13:12: warning: ‘my_init’ defined but not used [-Wunused-function]
static int my_init(void)
^~~~~~~
Compilation finished successfully.
Suggest enabling the warnings when compiling, then fix those warnings

Bison/Lex segfaults on x86 but runs on arm

I have a problem described in the title. I have an Edify language parser that runs without errors when I building it on arm but fails when I try to use it with x86. I traced segfault to yy_scan_bytes function, more precisely to this code:
YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) {
YY_BUFFER_STATE b;
char * buf;
yy_size_t n;
int i;
/* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2;
buf = (char *) yyalloc(n );
if ( ! buf ) {
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
}
for ( i = 0; i < _yybytes_len; ++i ) {
buf[i] = yybytes[i]; // <==========
}
The full code is here: https://github.com/twaik/edify_x86_failing_code
I've got it from AROMA Installer source.
That's everything I discovered after debug. Thanks.
Trying to build your code gives me these errors:
main.c: In function ‘parse_string’:
main.c:27:5: warning: implicit declaration of function ‘yy_switch_to_buffer’ [-W
implicit-function-declaration]
yy_switch_to_buffer(yy_scan_string(str));
^~~~~~~~~~~~~~~~~~~
main.c:27:25: warning: implicit declaration of function ‘yy_scan_string’ [-Wimplicit-function-declaration]
yy_switch_to_buffer(yy_scan_string(str));
That means that the compiler assumes that yy_switch_to_buffer() and yy_scan_string() return an int, as it does for all functions that are not declared before use (as per the c89 standard). But that is not the case (the first returns void, and the second a pointer (YY_BUFFER_STATE)). Notice that on x86_64, the size of a pointer is not the same as the size of an int.
Adding some band-aid prototypes like
void yy_switch_to_buffer(void*);
void *yy_scan_string(const char*);
to main.c, before their use in parse_string() may stop the segfaulting.
A better fix would be to arrange in the Makefile that the lexer be run with the --header-file=lex-header.h option, and then include lex-header.h from main.c. Or even better, wrap all lex-specific code in some simple functions, and put the prototypes of those functions in a header included from both main.c and the *.l file.

c compiler has a function stuck in its namespace (maybe?). mac

A week ago I made a function called getline in a code that didn't work. Since then, whenever I name a function getline and try to compile it, it doesn't work. If I change the name of the function to something else, it works again. I have restarted my computer (though it really shouldn't require that). How can I get this namespace back?
example error message:
Numens-MBP:c examples mycotic$ cc testing.c
testing.c:9:5: error: conflicting types for 'getline'
int getline(void);
^
/usr/include/stdio.h:448:9: note: previous declaration is here
ssize_t getline(char ** __restrict __linep, size_t * __restrict __lineca...
^
testing.c:13:1: warning: type specifier missing, defaults to 'int'
[-Wimplicit-int]
main()
^
testing.c:20:24: error: too few arguments to function call, expected 3, have 0
while ((len = getline()) > 0)
~~~~~~~ ^
/usr/include/stdio.h:448:1: note: 'getline' declared here
ssize_t getline(char ** __restrict __linep, size_t * __restrict __lineca...
^
testing.c:36:5: error: conflicting types for 'getline'
int getline(void)
^
/usr/include/stdio.h:448:9: note: previous declaration is here
ssize_t getline(char ** __restrict __linep, size_t * __restrict __lineca...
^
1 warning and 3 errors generated.
getline() is a standard C library function. Your function is conflicting with the definition in the standard library.
Pick another name for your function. This one is taken.
The getline() function is a part of POSIX 2008; it was not a part of POSIX 2001 or POSIX 1997. On a Mac, even when you specify -std=c11, the POSIX definitions are enabled by default.
You can work around it by specifying a POSIX version that did not support getline(). Consider this code — but ignore the fact that this 'getline()' outputs a line:
#include <stdio.h>
extern int getline(int);
int getline(int num)
{
printf("%s: %d\n", __func__, num);
return num + 1;
}
int main(void)
{
for (int i = 0; i < 5; i++)
printf("RV = %d\n", getline(i));
return 0;
}
When compiled with GCC 7.1.0, or with either the gcc or clang from XCode 8.3.2, generates all sorts of problems because of the conflicting type of getline() from POSIX and getline() as defined in this code unless you add arguments to prevent the problem. The source was in file gl23.c.
$ /usr/bin/clang -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
> -Wstrict-prototypes -Wold-style-definition gl23.c -o gl23
gl23.c:3:12: error: conflicting types for 'getline'
extern int getline(int);
^
/usr/include/stdio.h:448:9: note: previous declaration is here
ssize_t getline(char ** __restrict __linep, size_t * __restrict __linecapp, FILE * __restrict __stream) __OSX_AVAILABLE_STARTIN...
^
gl23.c:5:5: error: conflicting types for 'getline'
int getline(int num)
^
/usr/include/stdio.h:448:9: note: previous declaration is here
ssize_t getline(char ** __restrict __linep, size_t * __restrict __linecapp, FILE * __restrict __stream) __OSX_AVAILABLE_STARTIN...
^
gl23.c:14:38: error: too few arguments to function call, expected 3, have 1
printf("RV = %d\n", getline(i));
~~~~~~~ ^
/usr/include/stdio.h:448:1: note: 'getline' declared here
ssize_t getline(char ** __restrict __linep, size_t * __restrict __linecapp, FILE * __restrict __stream) __OSX_AVAILABLE_STARTIN...
^
3 errors generated.
$
However, if you specify conformance with the old versions of POSIX by adding -D_POSIX_C_SOURCE=200112L or -D_POSIX_C_SOURCE=199506L, then it compiles cleanly, and runs properly, producing:
getline: 0
RV = 1
getline: 1
RV = 2
getline: 2
RV = 3
getline: 3
RV = 4
getline: 4
RV = 5
Be aware that this is only a band-aid solution and it has ramifications — all the other nice new features of POSIX 2008 are no longer accessible.
The only long-term solution is to accept that getline() is now a part of the 'standard' C namespace — the standard is POSIX, of course, not ISO/IEC 9899:2011 — and rename the function. (Yes, it's a nuisance, and K&R 2nd Edition illustrates three versions of getline() that are no longer OK because of this. I had to rename my library function because of this. And the name was not in the reserved namespaces in prior versions of POSIX; there was no way to guess that it would be necessary.)

error: 'type name' declared as function returning a function

I'm developing a small library for a PID controller using avr-gcc.In spite of declaring the function in the header file and defining it separately in a .c file the compiler is throwing the following errors:
Compiling C: pid.c
avr-gcc -c -mmcu=atmega16 -I. -gdwarf-2 -DF_CPU=1000000UL -Os -funsigned-char -
funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-
adhlns=./pid.lst -std=gnu99 -MMD -MP -MF .dep/pid.o.d pid.c -o pid.o
pid.c:5: error: expected declaration specifiers or '...' before '(' token
pid.c:5: warning: function declaration isn't a prototype
pid.c:5: error: 'type name' declared as function returning a function
pid.c:5: error: conflicting types for 'PID_init'
pid.h:23: error: previous declaration of 'PID_init' was here
pid.c: In function 'PID_init':
pid.c:5: error: parameter name omitted
The header file contents of pid.h are as follows:
#include<avr/io.h>
#include<util/delay.h>
#ifndef PID_CONTROLLER
#define PID_CONTROLLER
struct PIDCONTROL
{
float error;
float prev_error;
float Kp;
float Ki;
float Kd;
float pid;
float P;
float I;
float D;
float setpoint;
};
void PID_init(float,float,float,float,struct PIDCONTROL*);
float PID(float,struct PIDCONTROL*);
#endif
The definitions for the declared functions have been made in pid.c which contains the code shown below:
#include<avr/io.h>
#include<util/delay.h>
#include "pid.h"
void PID_init(float SP,float Kp,float Ki,float Kd,struct PIDCONTROL *a)
{
a->Kp=Kp;
a->Ki=Ki;
a->Kd=Kd;
a->pid=0;
a->setpoint=SP;
a->prev_error=0;
}
float PID(float PV,struct PIDCONTROL *a)
{
a->error=(a->setpoint)-PV;
a->P=(a->Kp)*(a->error);
(a->I)+=(a->Ki)*(a->error)*1.024;
a->D=(a->Kd)*((a->error)-(a->prev_error))/1.024;
a->pid=(a->P)+(a->I)+(a->D);
a->prev_error=a->error;
return(a->pid);
}
I couldn't just figure out what's wrong with the code. Any help is appreciated.Thanks in advance.
The avr/io.h file also brings in avr/common.h which contains this little snippet:
/*
Stack pointer register.
AVR architecture 1 has no RAM, thus no stack pointer.
All other architectures do have a stack pointer. Some devices have only
less than 256 bytes of possible RAM locations (128 Bytes of SRAM
and no option for external RAM), thus SPH is officially "reserved"
for them.
*/
# ifndef SP
# define SP _SFR_MEM16(0x3D)
# endif
(it's actually a bit more complicated than that, with multiple paths depending on your architecture, but that cut down example shows what the actual problem is, at least).
It's actually defining a pre-processor macro for SP which means, when you attempt to use that in your code with a function definition along the lines of:
void PID_init(float SP,float Kp,float Ki,float Kd,struct PIDCONTROL *a)
what you'll actually get is something like:
void PID_init(float _SFR_MEM16(0x3D),float Kp,float Ki,float Kd,struct PIDCONTROL *a)
which will cause the compiler phase to complain bitterly.
I'm actually a big believer in reasonably self-describing variable names so would generally choose something more verbose than SP but you'll probably find that, even if you make it mySP, it'll fix the immediate problem.

my compiler says that this thing __attribute__ is wrong, a syntax error

The following is inside GNU m4 sources in a file called lib/verror.h :
/* Declaration for va_list error-reporting function
Copyright (C) 2006-2007, 2009-2011 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef _VERROR_H
#define _VERROR_H 1
#include "error.h"
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Print a message with `vfprintf (stderr, FORMAT, ARGS)';
if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
If STATUS is nonzero, terminate the program with `exit (STATUS)'.
Use the globals error_print_progname and error_message_count similarly
to error(). */
extern void verror (int __status, int __errnum, const char *__format,
va_list __args)
__attribute__ ((__format__ (__printf__, 3, 0)));
/* Print a message with `vfprintf (stderr, FORMAT, ARGS)';
if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
If STATUS is nonzero, terminate the program with `exit (STATUS)'.
If FNAME is not NULL, prepend the message with `FNAME:LINENO:'.
Use the globals error_print_progname, error_message_count, and
error_one_per_line similarly to error_at_line(). */
extern void verror_at_line (int __status, int __errnum, const char *__fname,
unsigned int __lineno, const char *__format,
va_list __args)
__attribute__ ((__format__ (__printf__, 5, 0)));
#ifdef __cplusplus
}
#endif
#endif /* verror.h */
My compiler blows up all over that strange thing called "attribute" and I looked
in the K&R C for it but can not find it.
Looks to be a strictly GNUism GCC thing and not C at all.
So the question is how to remove this junk to make the code able to be compiled
by an old C compiler on an old Sun server? The very same compiler can build GNU
make just fine as well as libiconv and gNU gettext but the latest GNU m4 looks
to be non-portable.
The error that I see is :
/opt/SUNWspro/bin/cc -I. -D_REENTRANT -I/usr/local/include -dy -xmemalign=8s -errfmt=error -erroff=%none -errshort=full -errwarn=%none -fns=no -ftrap=%none -xarch=v9 -xcode=pic32 -g -i -mc -Qy -v -Wl,-R/usr/local/lib -Xa -xstrconst -xtemp=/var/tmp -xunroll=1 -D_POSIX_PTHREAD_SEMANTICS -D_LARGEFILE64_SOURCE -D_TS_ERRNO -c verror.c
"verror.h", line 35: error: syntax error before or at: __attribute__
"verror.h", line 35: warning: old-style declaration or incorrect type for: __attribute__
"verror.h", line 35: warning: syntax error: empty declaration
"verror.h", line 47: error: syntax error before or at: __attribute__
"verror.h", line 47: warning: old-style declaration or incorrect type for: __attribute__
"verror.h", line 47: error: identifier redefined: __attribute__
current : function() returning int
previous: function() returning int : "verror.h", line 35
"verror.h", line 47: warning: syntax error: empty declaration
"verror.c", line 44: error: identifier redefined: verror
current : function(int, int, pointer to const char, pointer to void) returning void
previous: function(int, int, pointer to const char, pointer to void) returning void : "verror.h", line 33
"verror.c", line 57: error: identifier redefined: verror_at_line
current : function(int, int, pointer to const char, unsigned int, pointer to const char, pointer to void) returning void
previous: function(int, int, pointer to const char, unsigned int, pointer to const char, pointer to void) returning void : "verror.h", line 44
cc: acomp failed for verror.c
gmake[3]: *** [verror.o] Error 2
gmake[3]: Leaving directory `/usr/local/build/m4-1.4.16_SunOS5.8_sparcv9.001/lib'
gmake[2]: *** [all] Error 2
gmake[2]: Leaving directory `/usr/local/build/m4-1.4.16_SunOS5.8_sparcv9.001/lib'
gmake[1]: *** [all-recursive] Error 1
gmake[1]: Leaving directory `/usr/local/build/m4-1.4.16_SunOS5.8_sparcv9.001'
gmake: *** [all] Error 2
pretty nasty looking stuff that.
__attribute__ is a GCC extension, which has also been borrowed by clang and maybe other compilers as well. If your compiler doesn't support attributes using this syntax, you can get rid of the errors by defining this macro before any attributes are used:
#define __attribute__(x)
Keep in mind though that removing attributes may affect the program's behaviour.

Resources