kernelnewbies.kernelnewbies.org archive mirror
 help / color / mirror / Atom feed
* undefined reference to `__divdi3'
@ 2018-07-22 12:18 Himanshu Jha
       [not found] ` <CACnJAqP9JKzzg+dxsyLjfZ+Y5qp=APmjrqNKHbbTBjeF5U_kqQ@mail.gmail.com>
  2018-07-23 17:41 ` valdis.kletnieks at vt.edu
  0 siblings, 2 replies; 3+ messages in thread
From: Himanshu Jha @ 2018-07-22 12:18 UTC (permalink / raw)
  To: kernelnewbies

Hi,


I am currently working on my GSoC project and while testing through
0-day test service, I hit the following error:

   drivers/iio/chemical/bme680_core.o: In function `bme680_compensate_gas':
   drivers/iio/chemical/bme680_core.c:450: undefined reference to `__divdi3'

vim +450 drivers/iio/chemical/bme680_core.c

   417  
   418  /*
   419   * Taken from Bosch BME680 API:
   420   * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L973
   421   *
   422   * Returns gas measurement in Ohm. Output value of "82986" represent 82986 ohms.
   423   */
   424  static u32 bme680_compensate_gas(struct bme680_data *data, u16 gas_res_adc,
   425                                   u8 gas_range)
   426  {
   427          struct bme680_calib *calib = &data->bme680;
   428          s64 var1;
   429          u64 var2;
   430          s64 var3;
   431          u32 calc_gas_res;
   432  
   433          /* Look up table 1 for the possible gas range values */
   434          u32 lookupTable1[16] = {2147483647u, 2147483647u, 2147483647u,
   435                                  2147483647u, 2147483647u, 2126008810u,
   436                                  2147483647u, 2130303777u, 2147483647u,
   437                                  2147483647u, 2143188679u, 2136746228u,
   438                                  2147483647u, 2126008810u, 2147483647u,
   439                                  2147483647u};
   440          /* Look up table 2 for the possible gas range values */
   441          u32 lookupTable2[16] = {4096000000u, 2048000000u, 1024000000u,
   442                                  512000000u, 255744255u, 127110228u, 64000000u,
   443                                  32258064u, 16016016u, 8000000u, 4000000u,
   444                                  2000000u, 1000000u, 500000u, 250000u, 125000u};
   445  
   446          var1 = ((1340 + (5 * (s64) calib->range_sw_err)) *
   447                          ((s64) lookupTable1[gas_range])) >> 16;
   448          var2 = (((s64) ((s64) gas_res_adc << 15) - 16777216) + var1);
   449          var3 = (((s64) lookupTable2[gas_range] * (s64) var1) >> 9);
 > 450          calc_gas_res = (u32) ((var3 + ((s64) var2 >> 1)) / (s64) var2);
   451  
   452          return calc_gas_res;
   453  }

Now, I understood the problem of 64bit divison and how gcc places
'__divdi3()'
https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html
to support the "freestanding" environment and support architectures
which don't have such datatypes. And I need to use div64_s64()
or hack around do_div() to solve the issue.

Just out of curiosity, I decided to disassemble this particular function
to see __divdi3 and couldn't find it!

(gdb) disassemble bme680_compensate_gas
Dump of assembler code for function bme680_compensate_gas:
   0x0000000000000000 <+0>:	call   0x5 <bme680_compensate_gas+5>
   0x0000000000000005 <+5>:	sub    rsp,0x88
   0x000000000000000c <+12>:	movabs rcx,0x7eb851ea7fffffff
   0x0000000000000016 <+22>:	movzx  edx,dl
   0x0000000000000019 <+25>:	mov    rax,QWORD PTR gs:0x28
   0x0000000000000022 <+34>:	mov    QWORD PTR [rsp+0x80],rax
   0x000000000000002a <+42>:	xor    eax,eax
   0x000000000000002c <+44>:	movabs rax,0x7fffffff7fffffff
   0x0000000000000036 <+54>:	movabs r8,0x7ef9db217fffffff
   0x0000000000000040 <+64>:	movabs r9,0x7f5c28f47fbe76c7
   0x000000000000004a <+74>:	mov    QWORD PTR [rsp],rax
   0x000000000000004e <+78>:	mov    QWORD PTR [rsp+0x8],rax
   0x0000000000000053 <+83>:	movzx  esi,si
   0x0000000000000056 <+86>:	mov    QWORD PTR [rsp+0x20],rax
   0x000000000000005b <+91>:	mov    QWORD PTR [rsp+0x38],rax
   0x0000000000000060 <+96>:	movabs rax,0x7a120000f4240000
   0x000000000000006a <+106>:	mov    QWORD PTR [rsp+0x40],rax
   0x000000000000006f <+111>:	movabs rax,0x1e8480003d090000
   0x0000000000000079 <+121>:	mov    QWORD PTR [rsp+0x10],rcx
   0x000000000000007e <+126>:	mov    QWORD PTR [rsp+0x48],rax
   0x0000000000000083 <+131>:	movabs rax,0x7938c540f3e58ff
   0x000000000000008d <+141>:	mov    QWORD PTR [rsp+0x18],r8
   0x0000000000000092 <+146>:	mov    QWORD PTR [rsp+0x50],rax
   0x0000000000000097 <+151>:	movabs rax,0x1ec381003d09000
   0x00000000000000a1 <+161>:	mov    QWORD PTR [rsp+0x28],r9
   0x00000000000000a6 <+166>:	mov    QWORD PTR [rsp+0x58],rax
   0x00000000000000ab <+171>:	movabs rax,0x7a120000f46290
   0x00000000000000b5 <+181>:	mov    QWORD PTR [rsp+0x30],rcx
   0x00000000000000ba <+186>:	mov    QWORD PTR [rsp+0x60],rax
   0x00000000000000bf <+191>:	movabs rax,0x1e8480003d0900
   0x00000000000000c9 <+201>:	mov    ecx,DWORD PTR [rsp+rdx*4]
   0x00000000000000cc <+204>:	mov    QWORD PTR [rsp+0x68],rax
   0x00000000000000d1 <+209>:	movabs rax,0x7a120000f4240
   0x00000000000000db <+219>:	shl    rsi,0xf
   0x00000000000000df <+223>:	mov    QWORD PTR [rsp+0x70],rax
   0x00000000000000e4 <+228>:	movabs rax,0x1e8480003d090
   0x00000000000000ee <+238>:	mov    QWORD PTR [rsp+0x78],rax
   0x00000000000000f3 <+243>:	movsx  rax,BYTE PTR [rdi+0x2f]
   0x00000000000000f8 <+248>:	lea    rax,[rax+rax*4+0x53c]
   0x0000000000000100 <+256>:	imul   rax,rcx
   0x0000000000000104 <+260>:	sar    rax,0x10
   0x0000000000000108 <+264>:	lea    rsi,[rax+rsi*1-0x1000000]
   0x0000000000000110 <+272>:	mov    rcx,rax
   0x0000000000000113 <+275>:	mov    eax,DWORD PTR [rsp+rdx*4+0x40]
   0x0000000000000117 <+279>:	mov    rdx,rsi
   0x000000000000011a <+282>:	sar    rdx,1
   0x000000000000011d <+285>:	imul   rax,rcx
   0x0000000000000121 <+289>:	sar    rax,0x9
   0x0000000000000125 <+293>:	add    rax,rdx
   0x0000000000000128 <+296>:	cqo    
   0x000000000000012a <+298>:	idiv   rsi
   0x000000000000012d <+301>:	mov    rdi,QWORD PTR [rsp+0x80]
   0x0000000000000135 <+309>:	xor    rdi,QWORD PTR gs:0x28
   0x000000000000013e <+318>:	jne    0x148 <bme680_compensate_gas+328>
   0x0000000000000140 <+320>:	add    rsp,0x88
   0x0000000000000147 <+327>:	ret    
   0x0000000000000148 <+328>:	call   0x14d
End of assembler dump.

So, we have here:

	0x000000000000012a <+298>:   idiv   rsi

Now, my question is, will __divdi3() be generated when I compile using
 -m32 gcc flag or make ARCH=i386 ?

My machine is x86_64 and therefore idiv instruction is used instead of referencing
__divdi3(). Isn't it ?


Thanks.
-- 
Himanshu Jha
Undergraduate Student
Department of Electronics & Communication
Guru Tegh Bahadur Institute of Technology

^ permalink raw reply	[flat|nested] 3+ messages in thread

* undefined reference to `__divdi3'
       [not found] ` <CACnJAqP9JKzzg+dxsyLjfZ+Y5qp=APmjrqNKHbbTBjeF5U_kqQ@mail.gmail.com>
@ 2018-07-22 19:27   ` Himanshu Jha
  0 siblings, 0 replies; 3+ messages in thread
From: Himanshu Jha @ 2018-07-22 19:27 UTC (permalink / raw)
  To: kernelnewbies

Hi Alan,

On Sun, Jul 22, 2018 at 09:01:59PM +0200, Alan Keane wrote:
> Hi Himanshu,
> 
> >>
> Hi,
> 
> 
> I am currently working on my GSoC project and while testing through
> 0-day test service, I hit the following error:
> 
>    drivers/iio/chemical/bme680_core.o: In function `bme680_compensate_gas':
>    drivers/iio/chemical/bme680_core.c:450: undefined reference to `__divdi3'
> 
> <<
> 
> Are these errors that stop compilation or the compiler "just" giving
> warnings?

https://lists.01.org/pipermail/kbuild-all/2018-July/050481.html

> I'm guessing they are warnings because you have an object file that you can
> disassemble to find the idiv instruction?

Not sure to understand the question!?

> Are you building this code within the linux build system, I ask because I
> work a lot on bare metal systems and see a lot of these kind of warnings,
> on bare metal systems sometimes you have to implement __divdi3 (and
> friends) yourself, if your code does build (with warnings) does it link and
> most importantly does it (at least appear to) work?

Yes, I'm building within my linux machine.

The thing is when you do 64bit arithmetic operations in the code for an
architecture where there is no support for such operations(i386)

For instance in my code: 64 bit division

	calc_gas_res = (u32) ((var3 + ((s64) var2 >> 1)) / (s64) var2);

In such situations, gcc provides its own runtime library(libgcc.a or
libgcc_s.so.1) to perform those operations:

Runtime Function: long __divdi3 (long a, long b)

But the linker in the kernel compilation doesn't link libgcc and
therefore, we get this error.

To solve the problem we can do:

1. Use do_div() (look math64.h for more functions) to prevent build
error on 32bit environments.

2. Link statically libgcc using flags:
	-static-libgcc -lgcc

I have not cross-compiled for i386 and checked, but looking at kbuild
report it likely that build terminates and no linking takes place.

So, I need to use option 1. and test.
I'm sure div64_s64() would solve my problem.

Also, please avoid top-posting :)

-- 
Himanshu Jha
Undergraduate Student
Department of Electronics & Communication
Guru Tegh Bahadur Institute of Technology

^ permalink raw reply	[flat|nested] 3+ messages in thread

* undefined reference to `__divdi3'
  2018-07-22 12:18 undefined reference to `__divdi3' Himanshu Jha
       [not found] ` <CACnJAqP9JKzzg+dxsyLjfZ+Y5qp=APmjrqNKHbbTBjeF5U_kqQ@mail.gmail.com>
@ 2018-07-23 17:41 ` valdis.kletnieks at vt.edu
  1 sibling, 0 replies; 3+ messages in thread
From: valdis.kletnieks at vt.edu @ 2018-07-23 17:41 UTC (permalink / raw)
  To: kernelnewbies

On Sun, 22 Jul 2018 17:48:21 +0530, Himanshu Jha said:

> I am currently working on my GSoC project and while testing through
> 0-day test service, I hit the following error:

>    424  static u32 bme680_compensate_gas(struct bme680_data *data, u16 gas_res_adc,
>    425                                   u8 gas_range)
>    426  {
>    427          struct bme680_calib *calib = &data->bme680;
>    428          s64 var1;
>    429          u64 var2;
>    430          s64 var3;
>    431          u32 calc_gas_res;
>    432
>    433          /* Look up table 1 for the possible gas range values */
>    434          u32 lookupTable1[16] = {2147483647u, 2147483647u, 2147483647u,
>    435                                  2147483647u, 2147483647u, 2126008810u,
>    436                                  2147483647u, 2130303777u, 2147483647u,
>    437                                  2147483647u, 2143188679u, 2136746228u,
>    438                                  2147483647u, 2126008810u, 2147483647u,
>    439                                  2147483647u};

As an aside, making this a 'static u32' will get rid of the mess of mov and movabs
instructions each time.  'static const u32' would be even better, as then the
compiler knows it can optimize assuming it never changes any of the values...

(In addition, with all that initialization out of the picture, figuring out
which  assembler code does what should be easier...

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 486 bytes
Desc: not available
URL: <http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20180723/27536e06/attachment.sig>

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-07-23 17:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-22 12:18 undefined reference to `__divdi3' Himanshu Jha
     [not found] ` <CACnJAqP9JKzzg+dxsyLjfZ+Y5qp=APmjrqNKHbbTBjeF5U_kqQ@mail.gmail.com>
2018-07-22 19:27   ` Himanshu Jha
2018-07-23 17:41 ` valdis.kletnieks at vt.edu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).