Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefined reference to '__divdi3'

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

like image 479
DividedByZero Avatar asked Dec 30 '15 15:12

DividedByZero


1 Answers

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.

like image 175
John Bollinger Avatar answered Sep 20 '22 02:09

John Bollinger