代码之家  ›  专栏  ›  技术社区  ›  Alkis Mavridis

将llvm生成的目标代码与ld链接

  •  3
  • Alkis Mavridis  · 技术社区  · 6 年前

    我编写了一个小编译器,它使用llvm(通过c++)生成对象文件(在linux系统中)。

    当我将编译的输出与gcc链接时,程序运行良好:

    myCompiler source.mylang -o objCode
    gcc objCode -o program
    ./program #runs fine
    

    但如果我试图将其与ld链接,则在运行程序时会出现分段错误:

    myCompiler source.mylang -o objCode
    ld objCode -e main -o program   #ld does not print any error or warning.
    ./program #Segmentation fault (core dumped)
    

    以下是编译器输出的llvm代码(使用myLlvmModule->print函数):

    ; ModuleID = 'entryPointModule'
    source_filename = "entryPointModule"
    
    define i32 @main() {
    entry:
      %x = alloca i32
      store i32 55, i32* %x
      ret i32 0
      ret i32 0
    }
    

    当gcc成功时,为什么ld失败? 我以为在编写编译器之后,唯一需要的步骤就是调用链接器。是否需要其他编译器(如gcc)?

    如果是,为什么? 如果没有,我怎么能让ld工作呢?

    编辑: 工作二进制文件的readelf-d:

    Dynamic section at offset 0xe00 contains 24 entries:
      Tag        Type                         Name/Value
     0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
     0x000000000000000c (INIT)               0x4b8
     0x000000000000000d (FINI)               0x684
     0x0000000000000019 (INIT_ARRAY)         0x200df0
     0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)
     0x000000000000001a (FINI_ARRAY)         0x200df8
     0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
     0x000000006ffffef5 (GNU_HASH)           0x298
     0x0000000000000005 (STRTAB)             0x348
     0x0000000000000006 (SYMTAB)             0x2b8
     0x000000000000000a (STRSZ)              125 (bytes)
     0x000000000000000b (SYMENT)             24 (bytes)
     0x0000000000000015 (DEBUG)              0x0
     0x0000000000000003 (PLTGOT)             0x200fc0
     0x0000000000000007 (RELA)               0x3f8
     0x0000000000000008 (RELASZ)             192 (bytes)
     0x0000000000000009 (RELAENT)            24 (bytes)
     0x000000000000001e (FLAGS)              BIND_NOW
     0x000000006ffffffb (FLAGS_1)            Flags: NOW PIE
     0x000000006ffffffe (VERNEED)            0x3d8
     0x000000006fffffff (VERNEEDNUM)         1
     0x000000006ffffff0 (VERSYM)             0x3c6
     0x000000006ffffff9 (RELACOUNT)          3
     0x0000000000000000 (NULL)               0x0
    

    对损坏的二进制文件使用相同的命令:

    There is no dynamic section in this file.
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Florian Weimer    6 年前

    您的入口点试图返回不存在的堆栈上的返回地址,这就是程序跳转到零的原因。

    程序的入口点不应返回。它必须通过调用 _exit (或相关的系统调用)。