Upon linking some code that performs division and modulo operations on an integer of type long long I receive the following two errors:
util.c:(.text+0x1af): undefined reference to '__divdi3'
util.c:(.text+0x1ef): undefined reference to '__moddi3'
I have also tried using unsigned long long, however that results in the following error:
util.c:(.text+0x1af): undefined reference to '__udivdi3'
util.c:(.text+0x1ef): undefined reference to '__umoddi3'
Replacing the long long with int or long fixes the problem, but I need to use unsigned long long.
I am using the following command line to compile and link the program:
gcc -ffreestanding -c kernel/util.c -o kernel/util.o
ld -o kernel32.bin -Ttext 0x500 kernel/util.o kernel/kernel.o --oformat binary
and this is the function:
char* itoa(unsigned long long i, char b[]){
if (i == 0){
b[0] = '0';
b[1] = '\0';
return b;
}
char const digit[] = "0123456789";
char* p = b;
if (i < 0){
*p++ = '-';
i *= -1;
}
unsigned long long shifter = i;
while (shifter){
++p;
shifter = shifter / 10;
}
*p = '\0';
while (i){
*--p = digit[i % 10];
i = i / 10;
}
return b;
}
Clearly, the compiler is referencing __udivdi3 to divide the integer but the linker can't find it..
By the way, the binary is to be used as a 32 bit operating system and therefore lacks many standard libraries
EDIT: I am using gcc 4.8.4 and ld 2.24
When building code for an architecture that does not provide hardware support for the data type GCC uses as [unsigned] long long, GCC generates code for arithmetic operations on values of that type that involves calling functions provided by its own support library, libgcc. The __divdi3() etc. are among those. This is not the only way GCC could do it, but it is well suited to GCC's aim of supporting many architectures.
When instructed to act as a freestanding compiler, GCC does not automatically link libgcc, with the result that no implementation of these functions is automatically provided. This has been the subject of previous complaints, such as this one and this later one. The GCC maintainers take the position that this is not a GCC flaw, and that it does not render GCC non-conforming. I find their reasoning questionable, but it's unlikely to change. At minimum, this is a quality of implementation issue.
I do see where the GCC maintainers are coming from, however: a freestanding environment provides next to none of the standard library, and must not interpret most function calls except according to the code presented to it. What, then, if that code contains explicit calls to functions with the same names as some of those in libgcc? Unless the user explicitly says he wants libgcc, the compiler should not assume that it is those versions of the functions that are wanted. The problem, though, is that if the compiler inserts such calls, then not only does it know which implementations are intended, but the result is wrong if an incompatible one is linked instead. Thus, this is a problem of GCC's own making.
The bottom line is that you can explicitly request that libgcc be linked. You will want to specify that it be linked statically, as you cannot rely on a dynamic linker in your context. These additional link options should do it:
-static-libgcc -lgcc
Alternatively, you could write your own implementations of those functions, or crib the source from GCC, but I don't see why you would prefer either of those options.
Per this link: https://gcc.gnu.org/onlinedocs/gcc-3.3/gccint/Library-Calls.html
the functions of interest are defined in the libgcc.a library. (not in the libgcc.so library.)
I think your code will use the libgcc.a library if your link step contains the -static parameter
However, this link: https://sourceware.org/ml/crossgcc/2006-04/msg00000.html
has the following to say:
Typically you link with gcc instead of ld to avoid just these types of problems.
I would either change it to link using gcc, or add the proper -L and -l options to get it to use the proper libgcc
It seems that you are using the wrong function:
— Runtime Function: long __divdi3 (long a, long b)
I guess that the correct function is:
— Runtime Function: long long __divti3 (long long a, long long b)
(https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines)
Unfortunately I'm not sure if is implemented in your gcc version.
Related
Consider the following C code:
#include <stdio.h>
int x = 5;
int y = x-x+10;
int z = x*0+5;
int main()
{
printf("%d\n", y);
printf("%d\n", z);
return 0;
}
The ANSI C90 standard states "All the expressions for an object that has static storage duration [...] shall be constant expressions" (6.5.7 constraint 3).
Clearly the initializers for y and z are not constant expressions. And indeed, trying to compile the above C code with clang main.c or clang -ansi main.c gives an error for this reason.
However, compiling with gcc main.c or even gcc main.c -ansi -pedantic -Wextra -Wall gives no errors at all, and runs, printing 10 and 5.
On the other hand, trying something like the following:
#include <stdio.h>
int x = 5;
int main()
{
int y[x-x+2];
printf("%lu\n", sizeof(y));
return 0;
}
gives a warning when compiled with gcc -ansi -pedantic ... or clang -ansi -pedantic ....
So gcc randomly performs the mathematically correct cancellations in order to pretend that something is a constant expression, even when asked not to (-ansi). Why is this? Is this a bug?
By the way, my gcc version is 9.4.0 and my clang version is 10.0.0-4.
Without looking, there's one simple explanation: the code that checks whether the initializer is an acceptable constant expression operates on an internal representation after a pass that does arithmetic simplification, so it never "sees" your x-x or x*0.
This probably makes the implementation of the rule in GCC simpler: it just has to ask "is this node one that represents a constant?" rather than "is this tree one that I could evaluate as a constant later on?". It also facilitates the behavior that they probably want for the later standards (see below), and a special case for -ansi would probably add an undesirable amount of code complexity.
Is it a bug? Arguably. But it's one with such a small impact that it's not especially likely to get fixed. It works correctly for valid code, and it errors correctly on "really" invalid code that could actually cause a problem. It only deviates from the standard in a fairly harmless way, and only for C90 (since the C99 and later standards say "an implementation may accept other forms of constant expressions", which gives GCC latitude to allow an expression that mentions things not on the laundry list, as long as it has a constant value).
What argument type should I use in C when calling a Fortran function that takes logical arguments, specifically with gfortran? Where is this documented for gfortran?
Here's an example program that doesn't compile without warnings:
Contents of one.f:
subroutine proc1(x)
logical x
end
Contents of main.c:
void proc1_(_Bool *x);
int main() {
_Bool x;
proc1_(&x);
return 0;
}
If I compile using GCC as follows, with LTO enabled, I get a warning about mismatching function prototypes:
gfortran -flto -c one.f
gcc -flto -c main.c
gcc -flto main.o one.o
The warning I get:
main.c:2:6: warning: type of 'proc1_' does not match original declaration [-Wlto-type-mismatch]
2 | void proc1_(_Bool *x);
| ^
one.f:2:22: note: 'proc1' was previously declared here
2 | subroutine proc1(x)
| ^
one.f:2:22: note: code may be misoptimized unless '-fno-strict-aliasing' is used
Note that enabling LTO allows the linker to verify that argument types match between prototypes. Using LTO is unfortunately not our choice. CRAN requires the submitted code to compile without these warnings with LTO enabled.
I only see problems when trying to use logical arguments. real, integer and character are all fine.
gfortran can be asked to produce C prototypes, and this is the output it gives me:
gfortran -flto -fc-prototypes-external -c one.f
void proc1_ (int_fast32_t *x);
Using int_fast32_t in the C prototype doesn't work either. No type that I tried did, neither int, nor _Bool. Usually, when there is a type mismatch between prototypes, the error message mentions what the type should be—but not in this case.
How can I find what is the correct type to use?
For real modern C-Fortran interoperability you should use the types (kinds) supplied by the iso_c_binding module and make your Fortran procedure bind(c). That way you can use logical(c_bool).
In the old style the best thing is to work with integers and pass an int and only correct from integer to logical inside Fortran. Old C did not have any bool, it was added later.
With minimal changes:
subroutine proc1(x)
use iso_c_binding
logical(c_bool) x
end
#include <stdbool.h>
void proc1_(bool *x);
int main() {
bool x;
proc1_(&x);
return 0;
}
> gfortran -flto -c one.f
> gcc -flto -c main.c
> gcc -flto main.o one.o
issues no warning on my Linux and GCC 7 and 10.
Or after further changes:
subroutine proc1(x) bind(C, name="proc1")
use iso_c_binding
logical(c_bool), value :: x
end
#include <stdbool.h>
void proc1(bool x);
int main() {
bool x;
proc1(x);
return 0;
}
The change to pass-by-value of course only when it is indeed just an input parameter.
The correct and guaranteed to be portable solution is, as explained in the answer by Vladimir F, to create a Fortran wrapper routine that uses ISO_C_BINDING. This wrapper can also take the opportunity to make a more idiomatic C interface, e.g. using the value specifier to pass scalars by value.
However, for the quick and dirty solution that works on GFortran WITHOUT LTO (and somewhat likely on other compilers, but no guarantees), see https://gcc.gnu.org/onlinedocs/gfortran/Internal-representation-of-LOGICAL-variables.html#Internal-representation-of-LOGICAL-variables . That is, you can pass a C integer variable of the appropriate size containing 1 for true and 0 for false. Appropriate size here meaning that unless you have compiled your Fortran code with -fdefault-integer-8 or such compile options, the GFortran default kind logical will be 4 bytes, so a plain C int should be good (or int32_t if you really want to be sure, though I don't think GFortran supports any targets where the C int is not 32 bits).
The reason this doesn't work with LTO is that while the above works, in the bowels of GCC the Fortran LOGICAL variables are almost the same as integers, but not quite. So in practice they are special integer variables with max value 1 and min value 0 even though they take up more space (as specified by their kind parameter). So this kind of type mismatch is likely what it complains about. Unfortunately no solution to this one, except the above correct solution via ISO_C_BINDING.
I found that this code produces different results with "-fsanitize=undefined,address" and without it.
int printf(const char *, ...);
union {
long a;
short b;
int c;
} d;
int *e = &d.c;
int f, g;
long *h = &d.a;
int main() {
for (; f <= 0; f++) {
*h = g;
*e = 6;
}
printf("%d\n", d.b);
}
The command line is:
$ clang -O0 -fsanitize=undefined,address a.c -o out0
$ clang -O1 -fsanitize=undefined,address a.c -o out1
$ clang -O1 a.c -o out11
$ ./out0
6
$ ./out1
6
$ ./out11
0
The Clang version is:
$ clang -v
clang version 13.0.0 (/data/src/llvm-dev/llvm-project/clang 3eb2158f4fea90d56aeb200a5ca06f536c1df683)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /data/bin/llvm-dev/bin
Found candidate GCC installation: /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7
Selected GCC installation: /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7
Candidate multilib: .;#m64
Candidate multilib: 32;#m32
Selected multilib: .;#m64
Found CUDA installation: /usr/local/cuda, version 10.2
The OS and platform are:
CentOS Linux release 7.8.2003 (Core).0, x86_64 GNU/Linux
My questions:
Is there something wrong with my code? Is taking the address of multiple members of the union invalid in C?
If there is something wrong with my code, how do I get LLVM (or GCC) to warn me? I have used -Wall -Wextra but LLVM and GCC show no warning.
Is there something wrong with the code?
For practical purposes, yes.
I think this is the same underlying issue as Is it undefined behaviour to call a function with pointers to different elements of a union as arguments?
As Eric Postpischil points out, the C standard as read literally seems to permit your code, and require it to print out 6 (assuming that's consistent with how your implementation represents integer types and how it lays out unions). However, this literal reading would render the strict aliasing rule almost entirely impotent, so in my opinion it's not what the standard authors would have intended.
The spirit of the strict aliasing rule is that the same object may not be accessed through pointers to different types (with certain exceptions for character types, etc) and that the compiler may optimize on the assumption that this never happens. Although d.a and d.c are not strictly speaking "the same object", they do have overlapping storage, and I think compiler authors interpret the rule as also not allowing overlapping objects to be accessed through pointers to different types. Under that interpretation your code would have undefined behavior.
In Defect Report 236 the committee considered a similar example and stated that it has undefined behavior, because of its use of pointers that "have different types but designate the same region of storage". However, wording to clarify this does not seem to have ever made it into any subsequent version of the standard.
Anyhow, I think the practical upshot is that you cannot expect your code to work "correctly" under modern compilers that enforce their interpretations of the strict aliasing rule. Whether or not this is a clang bug is a matter of opinion, but even if you do think it is, then it's a bug that they are probably not ever going to fix.
Why does it behave this way?
If you use the -fno-strict-aliasing flag, then you get back to the 6 behavior. My guess is that the sanitizers happen to inhibit some of these optimizations, which is why you don't see the 0 behavior when using those options.
What seems to have happened under the hood with -O1 is the compiler assumed that the stores to *h and *e don't interact (because of their different types) and therefore can be freely reordered. So it hoisted *h = g outside the loop, since after all multiple stores to the same address, with no intervening load, are redundant and only the last one needs to be kept. It happened to put it after the loop, presumably because it can't prove that e doesn't point to g, so the value of g needs to be reloaded after the loop. So the final value of d.b is derived from *h = g which effectively does d.a = 0.
How to get a warning?
Unfortunately, compilers are not good at checking, either statically or at runtime, for violations of (their interpretation of) the strict aliasing rule. I'm not aware of any way to get a warning for such code. With clang you can use -Weverything to enable every warning option that it supports (many of which are useless or counterproductive), and even with that, it gives no relevant warnings about your program.
Another example
In case anyone is curious, here's another test case that doesn't rely on any type pun, reinterpretation, or other implementation-defined behavior.
#include <stdio.h>
short int zero = 0;
void a(int *pi, long *pl) {
for (int x = 0; x < 1000; x++) {
*pl = x;
*pi = zero;
}
}
int main(void) {
union { int i; long l; } u;
a(&u.i, &u.l);
printf("%d\n", u.i);
}
Try on godbolt
As read literally, this code would appear to print 0 on any implementation: the last assignment in a() was to u.i, so u.i should be the active member, and the printf should output the value 0 which was assigned to it. However, with clang -O2, the stores are reordered and the program outputs 999.
Just as a counterpoint, though, if you read the standard so as to make the above example UB, then this leads to the somewhat absurd conclusion that u.l = 0; u.i = 5; print(u.i); is well defined and prints 5, but that *&u.l = 0; *&u.i = 5; print(u.i); is UB. (Recall that the "cancellation rule" of & and * applies to &*p but not to *&x.)
The whole situation is rather unsatisfactory.
I will rewrite the code for ease of reading:
int printf(const char *, ...);
union
{
long l;
short s;
int i;
} u;
long *ul = &u.l;
int *ui = &u.i;
int counter, zero;
int main(void)
{
for (; counter <= 0; counter++)
{
*ul = zero;
*ui = 6;
}
printf("%d\n", u.s);
}
The only questionable code here is the use of u.s in the printf, when u.s is not the last member of the union that was stored. That is defined by C 2018 6.5.2.3, which says the value of u.s is that of the named member, and note 99 clarifies this means that, if s is not the member last used to store a value, the appropriate bytes are reinterpreted as a short. This is well established.
The other code is ordinary: *ul = zero; stores a value in a union member. There is no aliasing violating because ul points to a long and is used to access a long. *ui = 6; stores a value in another union member and is also not an aliasing violation.
The specific bytes used to represent 6 in an int are implementation-defined in regard to ordering and padding bits. However, whatever they are, they should be the same with or without Clang’s “sanitization” and the same in optimization levels 0 and 1. Therefore, the same result should be obtained in all compilations.
This is a compiler bug.
I agree with other comments and answer that this is likely a defect in the C standard, as it makes the aliasing rule largely useless. Nonetheless, the sample code conforms to the requirements of the C standard and ought to work as described.
The following test.c program
int main() {
dummySum(1, 2);
return 0;
}
int dummySum(int a, int b) {
return a + b;
}
...doesn't generate any warning when compiled with gcc -o test test.c, whereas the following one does:
int main() {
dummySum(1, 2);
return 0;
}
void dummySum(int a, int b) {
a + b;
}
Why?
When faced with an undeclared function, the compiler assumes a function that accepts the given number of arguments (I think) and returns int (that part I'm sure of). Your second one doesn't, and so you get the redefinition warning.
I believe, based on a very quick scan of the foreward, that C99 (PDF link) removed this. No great surprise that GCC still allows them (with a warning), though; I can't imagine how much code would start failing to compile...
Recommend using -Wall (turning on all warnings) so you get a huge amount of additional information (you can turn off specific warnings when you have a really good reason for whatever you're doing that generates them if need be).
A function cannot be used before it has been declared. When a function declaration is not visible, the implementation assumes in C89 that the function:
takes an unspecified (but fixed) number of parameters
returns an int
This is called an implicit function declaration.
In C99, implicit declarations of function have been removed of the language and the implementation is free to refuse to translate the source code.
Hopefully this is a very simple question. Following is the C pgm (test.c) I have.
#include <stdio.h>
//#include <stdlib.h>
int main (int argc, char *argv[]) {
int intValue = atoi("1");
double doubleValue = atof("2");
fprintf(stdout,"The intValue is %d and the doubleValue is %g\n", intValue, doubleValue);
return 0;
}
Note that I am using atoi() and atof() from stdlib.h, but I do not include that header file. I compile the pgm (gcc test.c) and get no compiler error!
I run the pgm (./a.out) and here is the output, which is wrong.
The intValue is 1 and the doubleValue is 0
Now I include stdlib.h (by removing the comments before the #include) and recompile it and run it again. This time I get the right output:
The intValue is 1 and the doubleValue is 2
How come the compiler did not complain about not including the stdlib.h and still let me use the atoi(), atof() functions?
My gcc info:
$ gcc --version
gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-27)
Any thoughts appreciated!
For historical reasons -- specifically, compatibility with very old C programs (pre-C89) -- using a function without having declared it first only provokes a warning from GCC, not an error. But the return type of such a function is assumed to be int, not double, which is why the program executes incorrectly.
If you use -Wall on the command line, you get a diagnostic:
$ gcc -Wall test.c
test.c: In function ‘main’:
test.c:5: warning: implicit declaration of function ‘atoi’
test.c:6: warning: implicit declaration of function ‘atof’
You should use -Wall basically always. Other very useful warning options for new code are -Wextra, -Wstrict-prototypes, -Wmissing-prototypes, -pedantic, and -Wwrite-strings, but compared to -Wall they have much higher false positive rates.
Tangentially: never use atoi nor atof, they hide input errors. Use strtol and strtod instead.
If you don't specify otherwise, I believe a C compiler will just guess that undeclared functions take the form extern int foo(). Which is why atoi works and atof doesn't. Which compiler flags were you using? I suggest using -Wall to turn on a bunch of gcc warnings, which should include referencing undeclared functions.
C allows you to call a function without having a declaration for that function.
The function will be assumed to return an int and arguments will be passed using default promotions. If those don't match what the function actually expects, you'll get undefined behavior.
Compilers will often warn for this case, but not always (and that will also depend on compiler configuration).
In C, when you use a function that was not declared, it assumes that it has the default prototype:
int FUNCTION_NAME();
Note that in C using () as prototype means it accepts any arguments.
If you compile with the flag -Wall (I recommend you to always use this flag, since it enables all recommended warnings) you will get a warning (not an error) telling you that you are using an undeclared function.
C, unfortunately, does not require functions to be prototyped (or even declared) before use -- but without a prototype, it automatically makes certain assumptions about the function. One of those is that it returns an int. In your case, atoi does return an int, so it works correctly. atof doesn't, so it doesn't work correctly. Lacking a prototype/declaration, you get undefined behavior -- typically it'll end up retrieving whatever value happens to be in the register where an int would normally be returned, and using that. It appears that in your particular case, that happens to be a zero, but it could just as easily be something else.
This is one of the reasons many people push "C++ as a better C" -- C++ does require that all functions be declared before use, and further that you specify the types of all (non-variadic) parameters as well (i.e. a C++ function declaration is like a C prototype, not like a C declaration).