undefined reference to __udivdi3

During the last month I have been playing with real-time scheduling in the Linux kernel. Basically, I’ve downloaded  the SCHED_DEADLINE implementation from their git repository and did some changes in some files in order to understand better how real-time task scheduling can be handled in Linux.

I used a 64-bit machine with Ubuntu and Eclipse CDT version to implement my modifications. You may wonder why did I use Eclipse? The answer to that is simply: Eclipse is one of the best tools that I know that besides being an excellent IDE (Integrated Development Environment) it has great code indexing and cross-reference capabilities. Moving on to the subject of this post, in my 64-bit machine I’m able to compile the modified version of kernel without any kind of problems but I’m not able to run my version. After some discussion with an expert in the subject, he told me that probably I wasn’t compiling the correct modules that would allow me to run the OS without any problems. After some thoughts on the subject, I decided to compile the same modified version in a 32-bit machine which I wasn’t using anymore, to see if I was able to, at least, run my modified version of the Linux kernel.

I confess that initially I thought that the compilation process would be smooth, but I got surprised when the code didn’t compile and gcc threw the error undefined reference to __udivdi3.

After some googling, I discovered that the error was thrown in a line where a division involving u64 data types was being conducted. Indeed I’ve found some good pointers to the problem, namely:

http://kerneltrap.org/mailarchive/linux-kernel-newbies/2009/2/5/4902104

https://bugs.launchpad.net/ubuntu/+source/linux-meta/+bug/237528

So, it looks like the problem is caused by a compatibility problem between the kernel sources and gcc v4.3. Well, that would make sense initially when I was using that version in the 32-bit machine. But after an upgrade of the gcc version to 4.4.3, I still get the error in my 32-bit machine and surprisingly with the same version in my 64-bit machine it compiles smoothly. So, is the error related to the machine’s architecture? Let’s see each machine’s architecture:

64-bit machine architecture: “model name    : AMD Turion(tm) X2 Dual-Core Mobile RM-74”

32-bit machine architecture: “model name    : Intel(R) M processor 1.60GHz”

After some googling (once again), I’ve found this thread that somehow fundaments my suspicions:

http://stackoverflow.com/questions/1063585/udivdi3-undefined-howto-find-code

Indeed it was an architecture issue. After modifying my code, by using the do_div function to perform a 64 bit division in a 32-bit architecture, the code compiled like a charm.

Regarding this type of operations, the following pointer is also helpful: http://www.captain.at/howto-udivdi3-umoddi3.php

And now let’s run the kernel ;).

Advertisements
    • Salvatore Di Francisi
    • February 19th, 2011

    Hi,
    on the post on the class of kernel linux Sched_deadline and the problem of division in the 32-bit systems, in this:

    Indeed it was an architecture issue. After modifying my code, by using the do_div function to perform a 64 bit division in a 32-bit architecture, the code compiled like a charm.

    Regarding this type of operations, the following pointer is also helpful: http://www.captain.at/howto-udivdi3-umoddi3.php

    The site is no longer working, as you have solved the problem exactly?
    I am very interested in the solution, thanks!

    • Hello Salvatore,

      Well it looks like I need to update the post!
      If my memory does not fail that link contained the definition of the macro and usage examples.

      Anyway, in order to solve the problem you may use div_u64(…) or do_div(…) functions to divide 64-bit values.
      If you follow this post http://stackoverflow.com/questions/1063585/udivdi3-undefined-howto-find-code,
      you will find an example on how to use the do_div macro.

      So, imagine that you want to divide two u64 values or one u64 value by a 32-bit value. To do that, you would use the macro in the following way:
      (demonstrated for two u64 values, for the second case you can use the function in the same way)


      u64 val_a = 10;
      u64 val_b = 5;

      // this variable stores the remainder of the division operation
      unsigned long int mod = 0;

      mod = do_div(val_a, val_b);

      After performing the call, val_a contains the result of the division operation ( val_a = 2) and mod = 0.

      The div_u64(…) follows the same behavioral pattern.

      I hope that this clarifies your doubts.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: