0 Replies - 2599 Views - Last Post: 04 March 2014 - 10:20 PM

#1 GunnerInc  Icon User is offline

  • "Hurry up and wait"
  • member icon




Reputation: 858
  • View blog
  • Posts: 2,282
  • Joined: 28-March 11

NASM/Linux - Getting the address of and using errno

Post icon  Posted 04 March 2014 - 10:20 PM

If you try using errno to check the result of a function call, you might get these errors when linking:
64-bit

Quote

/usr/bin/ld: errno: TLS definition in /lib/x86_64-linux-gnu/libc.so.6 section .tbss mismatches non-TLS reference in error.o
/lib/x86_64-linux-gnu/libc.so.6: error adding symbols: Bad value


32-bit

Quote

/usr/bin/ld: errno: TLS definition in /lib/i386-linux-gnu/libc.so.6 section .tbss mismatches non-TLS reference in error.o
/lib/i386-linux-gnu/libc.so.6: could not read symbols: Bad value


This is because errno is a macro. To fix this, we need to get the address of the errno variable.

64-bit
extern exit, strerror, printf, strtol, __errno_location

global main

section .data
ReallyRealyBigNum   db  "989789789875412198223423423423423423423423423423234784219879853243242342342342342344154987469", 0
fmtstr              db  "%s", 10, 0

section .bss
errno       resq    1

section .text
main:

    call    __errno_location                ; get address of errno
    mov     [errno], rax                    ; save it to our errno variable

    mov     rdx, 10                         ; base 10
    mov     rsi, 0                          ; don't need endptr
    mov     rdi, ReallyRealyBigNum          ; string that is way too big
    call    strtol                          ; try to convert
   
    mov     rdi, [errno]                    ; rdi = address of errno
    mov     rdi, [rdi]                      ; dereference to get value and pass as parameter
    call    strerror                        ; get pointer to error message string 

    mov     rsi, rax                        ; error message pointer
    mov     rdi, fmtstr                     ; 
    xor     rax, rax                        ; no xmm regs
    call    printf                          ; display error message

    mov     rdi, [errno]                    ; return error number 
    mov     rdi, [rdi]                      ; 
    call    exit                            ; goodbye



32-bit
extern exit, strerror, printf, strtol, __errno_location

global main

section .data
ReallyRealyBigNum   db  "989789789875412198223423423423423423423423423423234784219879853243242342342342342344154987469"
fmtstr              db  "%s", 10, 0

section .bss
errno               resd    1

section .text
 
main:
    call    __errno_location
    mov     [errno], eax
 
    push    10
    push    0
    push    ReallyRealyBigNum 
    call    strtol
    add     esp, 4 * 3

    mov     eax, [errno]
    mov     eax, [eax]
    push    eax
    call    strerror
    add     esp, 4 * 1
    
    push    eax
    push    fmtstr
    call    printf
    add     esp, 4 * 2

    mov     eax, [errno]
    mov     eax, [eax]
    push    eax
    call    exit


Running the code above will print "Numerical result out of range" to the terminal since they are too big.

What about clearing or setting errno before a function call?
    mov     rdi, [errno]
    mov     dword[rdi], 0 ; or any value

    mov     eax, [errno]
    mov     dword [eax], 0 ; or any value


Is This A Good Question/Topic? 0
  • +

Page 1 of 1