Search code examples
linuxubuntuassemblynasm

How to compile shared file with .bss section using nasm


I am trying to compile shared file from nasm I am using these commands:

nasm -f elf64 -o asm/asm.o asm/asm.asm
ld -shared -o asm/asm.so asm/asm.o -I/lib64/ld-linux-x86-64.so.2

after second one i got an error:

ld: asm/asm.o: relocation R_X86_64_32S against `.bss' can not be used when making a shared object; recompile with -fPIC
ld: final link failed: Nonrepresentable section on output

I cant use nasm -fPIC instead -f elf64 because it's invalid command. What should I do if I need .bss section maybe I can compile it in different way?

Here is my assembly code:

DEFAULT                 rel    
%include                "asm/python.inc"
GLOBAL                  PyInit_asm:function

SECTION         .rodata    
l_dubois_name           db "dubois", 0
l_module_name           db "asm", 0

SECTION         .bss
digitSpace resb 100
digitSpacePos resb 8


SECTION                 .data
l_asm_methods:              
ISTRUC PyMethodDef
  at PyMethodDef.ml_name    , dq l_dubois_name
  at PyMethodDef.ml_meth    , dq asm_dubois
  at PyMethodDef.ml_flags   , dq METH_NOARGS
  at PyMethodDef.ml_doc     , dq l_sayit_doc
IEND
NullMethodDef

l_asm_module:                ;; struct PyModuleDef *
ISTRUC PyModuleDef
  at PyModuleDef.m_base     , PyModuleDef_HEAD_INIT
  at PyModuleDef.m_name     , dq l_module_name
  at PyModuleDef.m_doc      , dq NULL
  at PyModuleDef.m_size     , dq -1
  at PyModuleDef.m_methods  , dq l_asm_methods
  at PyModuleDef.m_slots    , dq NULL
  at PyModuleDef.m_traverse , dq NULL
  at PyModuleDef.m_clear    , dq 0
  at PyModuleDef.m_free     , dq NULL
IEND

SECTION                 .text    
asm_dubois: 
    push rbp
    mov rbp, rsp
    mov rax, [rbp+62]
    mov rsp, rbp
    pop rbp
    call  _printRAX
    mov rax, 60
    mov rdi, 0
    syscall
        ret

_printRAX:
    mov rcx, digitSpace
    mov rbx, 10
    mov [rcx], rbx
    inc rcx
    mov [digitSpacePos], rcx

_printRAXLoop:
    mov rdx, 0
    mov rbx, 10
    div rbx
    push rax
    add rdx, 48
    mov rcx, [digitSpacePos]
    mov [rcx], dl
    inc rcx
    mov [digitSpacePos], rcx
    pop rax
    cmp rax, 0
    jne _printRAXLoop

_printRAXLoop2:
    mov rcx, [digitSpacePos]
    mov rax, 1
    mov rdi, 1
    mov rsi, rcx
    mov rdx, 1
    syscall
    mov rcx, [digitSpacePos]
    dec rcx
    mov [digitSpacePos], rcx
    cmp rcx, digitSpace
    jge _printRAXLoop2
    ret

Some random text for stackOverflow to accept mine code


Solution

  • The recompile with -fPIC error message is assuming that the asm / object file was created by a compiler. With hand-written asm you are the compiler and have to write position-independent code. (Or at least code that inefficiently uses 64-bit absolute addresses like your mov rcx, digitSpace; runtime fixups are supported for those relocations on GNU/Linux.)


    Use lea r8, [digitSpace] (or any convenient reg, preferably outside the loop) and compare against that.

    cmp rcx, digitSpace uses a static address as a 32-bit immediate sign-extended to 64-bit. This will require a R_X86_64_32S relocation: 64-bit address encoded as a 32-bit signed value. (Same as you'd get for [digitSpace + rdx] for example, that's another thing you can't do in PIC/PIE code)

    Only mov allows a 64-bit immediate (which NASM uses by default when you write mov r64, symbol). Of course it would be better to use a RIP-relative LEA like lea rcx, [digitSpace]. You used default rel so that will be RIP-relative).

    Almost exact duplicate of Assembler Error: Mach-O 64 bit does not support absolute 32 bit addresses (MacOS never allows using symbol addresses as 32-bit immediates so it's an assemble-time error, vs. on Linux only an error when you try to link into an ELF shared object instead of a non-PIE executable.)

    Also related: