Stream: cranelift

Topic: error calling malloc from Cranelift


view this post on Zulip Teymour Aldridge (Dec 27 2021 at 20:24):

I'm trying to use Cranelift to call malloc, with the following IR:

function u0:0() -> i64 system_v {
    sig0 = (i64) -> i64 system_v
    sig1 = (i64) -> i64 system_v
    fn0 = u0:1 sig0
    fn1 = u0:2 sig1

block0:
    v0 = iconst.i64 20
    v1 = iconst.i64 8
    v2 = imul v0, v1
    v3 = call fn0(v2)
    v4 = call fn1(v3)
    v5 = iconst.i64 0
    return v5
}

fn0 is (should be?) malloc and fn1 is (should be?) free.

This compiles fine on x86_64 MacOS, however, when I emit an object file (using cranelift-module), link with cc and run it, I obtain the following error:

dyld: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB has segment 1 which is not writable in /<redacted>/examples/./a.out
zsh: abort      ./a.out

I'm not sure if I'm doing something wrong (most likely) or this is a bug in Cranelift – any help would be much appreciated.

view this post on Zulip bjorn3 (Dec 27 2021 at 20:41):

@Teymour Aldridge Can you run otool -hltdr ./a.out?

view this post on Zulip Teymour Aldridge (Dec 27 2021 at 20:42):

Yes:

./a.out:
Mach header
      magic  cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedfacf 16777223          3  0x00           2    14        744 0x00000085
Load command 0
      cmd LC_SEGMENT_64
  cmdsize 72
  segname __PAGEZERO
   vmaddr 0x0000000000000000
   vmsize 0x0000000100000000
  fileoff 0
 filesize 0
  maxprot 0x00000000
 initprot 0x00000000
   nsects 0
    flags 0x0
Load command 1
      cmd LC_SEGMENT_64
  cmdsize 232
  segname __TEXT
   vmaddr 0x0000000100000000
   vmsize 0x0000000000004000
  fileoff 0
 filesize 16384
  maxprot 0x00000005
 initprot 0x00000005
   nsects 2
    flags 0x0
Section
  sectname __text
   segname __TEXT
      addr 0x0000000100003f88
      size 0x0000000000000030
    offset 16264
     align 2^0 (1)
    reloff 0
    nreloc 0
     flags 0x80000600
 reserved1 0
 reserved2 0
Section
  sectname __unwind_info
   segname __TEXT
      addr 0x0000000100003fb8
      size 0x0000000000000048
    offset 16312
     align 2^2 (4)
    reloff 0
    nreloc 0
     flags 0x00000000
 reserved1 0
 reserved2 0
Load command 2
      cmd LC_SEGMENT_64
  cmdsize 72
  segname __LINKEDIT
   vmaddr 0x0000000100004000
   vmsize 0x0000000000004000
  fileoff 16384
 filesize 240
  maxprot 0x00000001
 initprot 0x00000001
   nsects 0
    flags 0x0
Load command 3
            cmd LC_DYLD_INFO_ONLY
        cmdsize 48
     rebase_off 0
    rebase_size 0
       bind_off 16384
      bind_size 40
  weak_bind_off 0
 weak_bind_size 0
  lazy_bind_off 0
 lazy_bind_size 0
     export_off 16424
    export_size 48
Load command 4
     cmd LC_SYMTAB
 cmdsize 24
  symoff 16480
   nsyms 5
  stroff 16560
 strsize 64
Load command 5
            cmd LC_DYSYMTAB
        cmdsize 80
      ilocalsym 0
      nlocalsym 0
     iextdefsym 0
     nextdefsym 2
      iundefsym 2
      nundefsym 3
         tocoff 0
           ntoc 0
      modtaboff 0
        nmodtab 0
   extrefsymoff 0
    nextrefsyms 0
 indirectsymoff 0
  nindirectsyms 0
      extreloff 0
        nextrel 0
      locreloff 0
        nlocrel 0
Load command 6
          cmd LC_LOAD_DYLINKER
      cmdsize 32
         name /usr/lib/dyld (offset 12)
Load command 7
     cmd LC_UUID
 cmdsize 24
    uuid 9D372077-63F5-3F81-9AEC-969682BFFD4B
Load command 8
      cmd LC_BUILD_VERSION
  cmdsize 32
 platform 1
    minos 10.15
      sdk 10.15.6
   ntools 1
     tool 3
  version 609.8
Load command 9
      cmd LC_SOURCE_VERSION
  cmdsize 16
  version 0.0
Load command 10
       cmd LC_MAIN
   cmdsize 24
  entryoff 16264
 stacksize 0
Load command 11
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name /usr/lib/libSystem.B.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1281.100.1
compatibility version 1.0.0
Load command 12
      cmd LC_FUNCTION_STARTS
  cmdsize 16
  dataoff 16472
 datasize 8
Load command 13
      cmd LC_DATA_IN_CODE
  cmdsize 16
  dataoff 16480
 datasize 0
(__TEXT,__text) section
0000000100003f88 55 48 89 e5 bf 08 00 00 00 48 6b ff 14 48 be 00
0000000100003f98 00 00 00 00 00 00 00 ff d6 48 89 c7 48 be 00 00
0000000100003fa8 00 00 00 00 00 00 ff d6 48 31 c0 48 89 ec 5d c3

view this post on Zulip bjorn3 (Dec 27 2021 at 20:49):

Just to confirm you are on x86_64, right?

view this post on Zulip bjorn3 (Dec 27 2021 at 20:50):

Also can you run the same command on the original object file before linking?

view this post on Zulip bjorn3 (Dec 27 2021 at 20:51):

Does it still error if you omit one or both of the calls?

view this post on Zulip Teymour Aldridge (Dec 28 2021 at 10:26):

I'm on MacOS Catalina, x86_64.

I don't the see the error if I emit both calls.

When I run the command on the object file I get this output:

program.o:
Mach header
      magic  cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedfacf 16777223          3  0x00           1     2        176 0x00000000
Load command 0
      cmd LC_SEGMENT_64
  cmdsize 152
  segname
   vmaddr 0x0000000000000000
   vmsize 0x0000000000000030
  fileoff 208
 filesize 48
  maxprot 0x00000007
 initprot 0x00000007
   nsects 1
    flags 0x0
Section
  sectname __text
   segname __TEXT
      addr 0x0000000000000000
      size 0x0000000000000030
    offset 208
     align 2^0 (1)
    reloff 328
    nreloc 2
     flags 0x80000400
 reserved1 0
 reserved2 0
Load command 1
     cmd LC_SYMTAB
 cmdsize 24
  symoff 256
   nsyms 3
  stroff 304
 strsize 21
Relocation information (__TEXT,__text) 2 entries
address  pcrel length extern type    scattered symbolnum/value
0000000f 0     3      1      0       0         1
0000001e 0     3      1      0       0         2
(__TEXT,__text) section
0000000000000000 55 48 89 e5 bf 08 00 00 00 48 6b ff 14 48 be 00
0000000000000010 00 00 00 00 00 00 00 ff d6 48 89 c7 48 be 00 00
0000000000000020 00 00 00 00 00 00 ff d6 48 31 c0 48 89 ec 5d c3

The error doesn't appear if I omit both calls.

function u0:0() -> i64 system_v {
block0:
    v0 = iconst.i64 0
    return v0
}

It does appear if I just omit the call to free:

function u0:0() -> i64 system_v {
    sig0 = (i64) -> i64 system_v
    fn0 = u0:1 sig0

block0:
    v0 = iconst.i64 20
    v1 = iconst.i64 8
    v2 = imul v0, v1
    v3 = call fn0(v2)
    v4 = iconst.i64 0
    return v4
}

view this post on Zulip Teymour Aldridge (Dec 28 2021 at 15:38):

Weirdly enough, I compiled the same program (instantiating the module for Linux) on Linux (Fedora) and it worked fine.

view this post on Zulip bjorn3 (Dec 28 2021 at 16:44):

Strange. I don't have a clue what could be going wrong.

view this post on Zulip Teymour Aldridge (Dec 28 2021 at 16:59):

Me too! I searched the internet quite a bit and couldn't find anything, so I thought it might be worth asking here.

Do you know of any examples (source-viewable code ideally) using Cranelift and malloc on MacOS?

view this post on Zulip Teymour Aldridge (Dec 28 2021 at 17:45):

I _think_ there has been a related bug in LLVM: https://lists.llvm.org/pipermail/llvm-dev/2017-July/115222.html

view this post on Zulip Teymour Aldridge (Dec 28 2021 at 20:25):

I managed to fix it!
details: https://github.com/bailion/compiler/commit/909f733af57e33f939940bdfbad4ed36a6bc9b72

Turns out PIC is needed on MacOS (I think at least).

Thank you for your help!

The error previously was (on one line) ``` dyld: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB has segment 1 which is not writable in /<redacted>/examples/./a.out ``` The issue was that Cranelift ...

view this post on Zulip bjorn3 (Dec 28 2021 at 21:07):

Nice! That explains why cg_clif doesn't hit this issue.


Last updated: Nov 22 2024 at 16:03 UTC