flat assembler
Message board for the users of flat assembler.

Index > Linux > (solved)PIC WIP My attempt to call lib functions from my lib

Author
Thread Post new topic Reply to topic
eilenbeb



Joined: 17 Feb 2010
Posts: 21
eilenbeb
EDIT changed the thread title to be more useful.
EDIT ...the first 2 posts are my first attempt. See the rest for updates.

So I've managed to generate and use a lib. The problem is that when I try to use a function from another lib, ld chokes.
Code:
fasm misc.fasm libmisc.o
ld -m elf_x86_64 -shared -fPIC -lc -o libmisc.so -soname libmisc.so libmisc.o
ld: libmisc.o: relocation R_X86_64_PC32 against undefined symbol `puts@@GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
ld: final link failed: Bad value
    

...and here's the code for my 'lib'
Code:
format ELF64
public szout
extrn 'puts' as _puts
    puts = PLT _puts

section '.text' executable
;--------------------------
szout:
        call puts
        ret
;--------------------------
    

I usually generate my own elf64 header, so I'm quite new at using ld.
Hopefully I'm just making a simple mistake, but I've been fighting with this for a while now.


Last edited by eilenbeb on 02 Dec 2014, 22:19; edited 2 times in total
Post 13 Nov 2014, 02:01
View user's profile Send private message Reply with quote
eilenbeb



Joined: 17 Feb 2010
Posts: 21
eilenbeb
The above will build if I comment out the 'call puts' line, and then I can get an objdump:
Code:
libmisc.so:     file format elf64-x86-64
libmisc.so
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000000238

Program Header:
    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21
         filesz 0x0000000000000240 memsz 0x0000000000000240 flags r-x
    LOAD off    0x0000000000000240 vaddr 0x0000000000200240 paddr 0x0000000000200240 align 2**21
         filesz 0x0000000000000110 memsz 0x0000000000000110 flags rw-
 DYNAMIC off    0x0000000000000240 vaddr 0x0000000000200240 paddr 0x0000000000200240 align 2**3
         filesz 0x0000000000000110 memsz 0x0000000000000110 flags rw-

Dynamic Section:
  NEEDED               libc.so.6
  SONAME               libmisc.so
  AUXILIARY            PIC
  HASH                 0x00000000000000e8
  STRTAB               0x00000000000001c0
  SYMTAB               0x0000000000000118
  STRSZ                0x0000000000000049
  SYMENT               0x0000000000000018
  VERNEED              0x0000000000000218
  VERNEEDNUM           0x0000000000000001
  VERSYM               0x000000000000020a

Version References:
  required from libc.so.6:
    0x09691a75 0x00 02 GLIBC_2.2.5

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .hash         00000030  00000000000000e8  00000000000000e8  000000e8  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .dynsym       000000a8  0000000000000118  0000000000000118  00000118  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .dynstr       00000049  00000000000001c0  00000000000001c0  000001c0  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .gnu.version  0000000e  000000000000020a  000000000000020a  0000020a  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .gnu.version_r 00000020  0000000000000218  0000000000000218  00000218  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .text         00000001  0000000000000238  0000000000000238  00000238  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  6 .eh_frame     00000000  0000000000000240  0000000000000240  00000240  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .dynamic      00000110  0000000000200240  0000000000200240  00000240  2**3
                  CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
00000000000000e8 l    d  .hash  0000000000000000              .hash
0000000000000118 l    d  .dynsym        0000000000000000              .dynsym
00000000000001c0 l    d  .dynstr        0000000000000000              .dynstr
000000000000020a l    d  .gnu.version   0000000000000000              .gnu.version
0000000000000218 l    d  .gnu.version_r 0000000000000000              .gnu.version_r
0000000000000238 l    d  .text  0000000000000000              .text
0000000000000240 l    d  .eh_frame      0000000000000000              .eh_frame
0000000000200240 l    d  .dynamic       0000000000000000              .dynamic
0000000000200240 l     O .dynamic       0000000000000000              _DYNAMIC
0000000000000000 l     O .dynamic       0000000000000000              _GLOBAL_OFFSET_TABLE_
0000000000000000       F *UND*  0000000000000000              puts@@GLIBC_2.2.5
0000000000200350 g       .dynamic       0000000000000000              _edata
0000000000000238 g     F .text  0000000000000000              szout
0000000000200350 g       .dynamic       0000000000000000              _end
0000000000200350 g       .dynamic       0000000000000000              __bss_start
    
Post 13 Nov 2014, 02:09
View user's profile Send private message Reply with quote
eilenbeb



Joined: 17 Feb 2010
Posts: 21
eilenbeb
Partial success! here's the lib test code:
Code:
format ELF64
ALIGN 8
public szout
extrn puts              ;; the PLT op was no-go
                                ;; had to set w .text
section '.text' writeable executable
;--------------------------
szout:
        lea rax,[puts]
        sub rax,4
        call rax        ;; string pointer still in rdi
        ret
;--------------------------    

NOTE! 'puts' is actually pointing to libc-2.20.so::puts+4 !!!
so there' still something wrong. by loading puts into rax and adjusting rax, things 'work'.
'.text' had to be set writeable. That's what was fsck'ing up ld.
I had no luck of any kind using the PLT operator. It was pointing someplace weird.
Lastly, here's my build command.
Code:
#! /bin/bash
fasm misc.fasm libmisc.o
ld -m elf_x86_64 -shared -o libmisc.so -h libmisc.so libmisc.o -l:/lib/libc-2.20.so
xterm -e sudo cp libmisc.so /lib/libmisc.so    

Note that the lib has to be 'installed' otherwise you need a funny command to launch a test program (wreaks havok on my debugger)
I'll keep experimenting with this, but feel free to shout if you've any ideas for me.
Post 13 Nov 2014, 22:52
View user's profile Send private message Reply with quote
eilenbeb



Joined: 17 Feb 2010
Posts: 21
eilenbeb
oops, here's the latest objdump
Code:
libmisc.so:     file format elf64-x86-64
libmisc.so
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000000250

Program Header:
    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21
         filesz 0x0000000000000260 memsz 0x0000000000000260 flags r-x
    LOAD off    0x0000000000000260 vaddr 0x0000000000200260 paddr 0x0000000000200260 align 2**21
         filesz 0x0000000000000140 memsz 0x0000000000000140 flags rw-
 DYNAMIC off    0x0000000000000260 vaddr 0x0000000000200260 paddr 0x0000000000200260 align 2**3
         filesz 0x0000000000000140 memsz 0x0000000000000140 flags rw-

Dynamic Section:
  NEEDED               libc.so.6
  SONAME               libmisc.so
  HASH                 0x00000000000000e8
  STRTAB               0x00000000000001c0
  SYMTAB               0x0000000000000118
  STRSZ                0x0000000000000045
  SYMENT               0x0000000000000018
  RELA                 0x0000000000000238
  RELASZ               0x0000000000000018
  RELAENT              0x0000000000000018
  TEXTREL              0x0000000000000000
  VERNEED              0x0000000000000218
  VERNEEDNUM           0x0000000000000001
  VERSYM               0x0000000000000206

Version References:
  required from libc.so.6:
    0x09691a75 0x00 02 GLIBC_2.2.5

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .hash         00000030  00000000000000e8  00000000000000e8  000000e8  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .dynsym       000000a8  0000000000000118  0000000000000118  00000118  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .dynstr       00000045  00000000000001c0  00000000000001c0  000001c0  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .gnu.version  0000000e  0000000000000206  0000000000000206  00000206  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .gnu.version_r 00000020  0000000000000218  0000000000000218  00000218  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .rela.dyn     00000018  0000000000000238  0000000000000238  00000238  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .text         0000000e  0000000000000250  0000000000000250  00000250  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  7 .eh_frame     00000000  0000000000000260  0000000000000260  00000260  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .dynamic      00000140  0000000000200260  0000000000200260  00000260  2**3
                  CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
00000000000000e8 l    d  .hash  0000000000000000              .hash
0000000000000118 l    d  .dynsym        0000000000000000              .dynsym
00000000000001c0 l    d  .dynstr        0000000000000000              .dynstr
0000000000000206 l    d  .gnu.version   0000000000000000              .gnu.version
0000000000000218 l    d  .gnu.version_r 0000000000000000              .gnu.version_r
0000000000000238 l    d  .rela.dyn      0000000000000000              .rela.dyn
0000000000000250 l    d  .text  0000000000000000              .text
0000000000000260 l    d  .eh_frame      0000000000000000              .eh_frame
0000000000200260 l    d  .dynamic       0000000000000000              .dynamic
0000000000200260 l     O .dynamic       0000000000000000              _DYNAMIC
0000000000000000 l     O .dynamic       0000000000000000              _GLOBAL_OFFSET_TABLE_
0000000000000000       F *UND*  0000000000000000              puts@@GLIBC_2.2.5
00000000002003a0 g       .dynamic       0000000000000000              _edata
0000000000000250 g     F .text  0000000000000000              szout
00000000002003a0 g       .dynamic       0000000000000000              _end
00000000002003a0 g       .dynamic       0000000000000000              __bss_start    
Post 13 Nov 2014, 22:55
View user's profile Send private message Reply with quote
eilenbeb



Joined: 17 Feb 2010
Posts: 21
eilenbeb
Update: data access.
I've discovered that any data storage to be written/read must be in a '.data' section marked 'writeable'...
UNLESS I comment out the '.text' declaration. Then I can define (and use) any data anywhere.
Handy for per-function static or local non-stack storage.
Anyone have any thoughts on this method?

I'm now calling 2 libc funcs and both of their addresses are off by 4. Time to add another external lib and see what effect that has.

EDIT: not worth a new post, but libc is a no-go. Need 2 seperate libs that DON'T require each other (or pull the other in). Delays: gotta find new exteral libs that don't require too much research. Again,feel free to pipe in.
ATM I'm thinking about opengl + freeimage, just for a test.
SRSLY anybody got any ideas why 'func' is off by 4?
Post 13 Nov 2014, 23:59
View user's profile Send private message Reply with quote
evk1



Joined: 18 Jun 2014
Posts: 24
evk1
Hi eilenbeb,
Some time ago I was working at the same problem, but my goal was to generate and use library with pure FASM. Unfortunately I was using ELF32, so I cannot define the problem exactly, but I think it is connected with RIP-relative addressing and ELF relocations for it. Could you provide an objdump for libmisc.o or at least its relocation section?
Anyway you can use something like lea rax,[puts-4].

P.S. You have written, you have some experience in building ELF files from scratch, but in spite of this, you use ld. Why?

_________________
Sorry for my English
Post 14 Nov 2014, 18:47
View user's profile Send private message Reply with quote
eilenbeb



Joined: 17 Feb 2010
Posts: 21
eilenbeb
Hi. Sorry but I got busy and haven't done any more on this. Everything's on another system, I'll try to take a look later if I have time.

For some reason, the '-4' had no effect. Didn't understand that one, still at a loss.
I'm only using ld until I can get a small, simple, working lib that references 2-4 funcs from 2 external libs. Then I'll start work on writing my own relocate headers.
To put it simply, I don't know how yet.
Post 17 Nov 2014, 17:19
View user's profile Send private message Reply with quote
eilenbeb



Joined: 17 Feb 2010
Posts: 21
eilenbeb
Ok. Sorry for dalays. I've still made no progress.
Since nothing is working right, I decided to re-simplify: here's my 'lib'
Code:
format ELF64
extrn puts
public szout
;--------------------------
szout:
        call puts
        call plt puts
        ret
;--------------------------    

When I run my test prog through the debugger, the 2 calls are the same. The plt operator seems to have no effect.
I've been playing with every 'relocatable' and 'dynamic' thing I can find in the ld manpage, but nothing seems to make a difference.
I can still 'lea rax,blah' then subtract 4. Works fine, if you call that working.
I don't like my rax being tied up like that.
Here's my ld:
Code:
ld -m elf_x86_64 -shared -o libmisc.so -h libmisc.so libmisc.o -l:/lib/libc-2.20.so    

So... I'm still at a total loss here. You (evk1) requested the objdump (-x?) frrom libmisc.o (??? NOT libmisc.so ???)
Ok, objdump -x libmisc.o:
Code:
libmisc.o
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .flat         0000000b  0000000000000000  0000000000000000  00000040  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, CODE
SYMBOL TABLE:
0000000000000000 l    d  .flat  0000000000000000 .flat
0000000000000000         *UND*  0000000000000000 puts
0000000000000000 g     F .flat  0000000000000000 szout


RELOCATION RECORDS FOR [.flat]:
OFFSET           TYPE              VALUE 
0000000000000001 R_X86_64_PC32     puts
0000000000000006 R_X86_64_PC32     put    

objdump -x libmisc.so
Code:
libmisc.so:     file format elf64-x86-64
libmisc.so
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000000000

Program Header:
    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21
         filesz 0x0000000000000268 memsz 0x0000000000000268 flags r--
    LOAD off    0x0000000000000268 vaddr 0x0000000000200268 paddr 0x0000000000200268 align 2**21
         filesz 0x000000000000013b memsz 0x000000000000013b flags rwx
 DYNAMIC off    0x0000000000000268 vaddr 0x0000000000200268 paddr 0x0000000000200268 align 2**3
         filesz 0x0000000000000130 memsz 0x0000000000000130 flags rw-

Dynamic Section:
  NEEDED               libc.so.6
  SONAME               libmisc.so
  HASH                 0x00000000000000e8
  STRTAB               0x00000000000001c0
  SYMTAB               0x0000000000000118
  STRSZ                0x0000000000000045
  SYMENT               0x0000000000000018
  RELA                 0x0000000000000238
  RELASZ               0x0000000000000030
  RELAENT              0x0000000000000018
  VERNEED              0x0000000000000218
  VERNEEDNUM           0x0000000000000001
  VERSYM               0x0000000000000206

Version References:
  required from libc.so.6:
    0x09691a75 0x00 02 GLIBC_2.2.5

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .hash         00000030  00000000000000e8  00000000000000e8  000000e8  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .dynsym       000000a8  0000000000000118  0000000000000118  00000118  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .dynstr       00000045  00000000000001c0  00000000000001c0  000001c0  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .gnu.version  0000000e  0000000000000206  0000000000000206  00000206  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .gnu.version_r 00000020  0000000000000218  0000000000000218  00000218  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .rela.dyn     00000030  0000000000000238  0000000000000238  00000238  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .eh_frame     00000000  0000000000000268  0000000000000268  00000268  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .dynamic      00000130  0000000000200268  0000000000200268  00000268  2**3
                  CONTENTS, ALLOC, LOAD, DATA
  8 .flat         0000000b  0000000000200398  0000000000200398  00000398  2**3
                  CONTENTS, ALLOC, LOAD, CODE
SYMBOL TABLE:
00000000000000e8 l    d  .hash  0000000000000000              .hash
0000000000000118 l    d  .dynsym        0000000000000000              .dynsym
00000000000001c0 l    d  .dynstr        0000000000000000              .dynstr
0000000000000206 l    d  .gnu.version   0000000000000000              .gnu.version
0000000000000218 l    d  .gnu.version_r 0000000000000000              .gnu.version_r
0000000000000238 l    d  .rela.dyn      0000000000000000              .rela.dyn
0000000000000268 l    d  .eh_frame      0000000000000000              .eh_frame
0000000000200268 l    d  .dynamic       0000000000000000              .dynamic
0000000000200398 l    d  .flat  0000000000000000              .flat
0000000000200268 l     O .dynamic       0000000000000000              _DYNAMIC
0000000000000000 l     O .dynamic       0000000000000000              _GLOBAL_OFFSET_TABLE_
0000000000000000       F *UND*  0000000000000000              puts@@GLIBC_2.2.5
00000000002003a3 g       .flat  0000000000000000              _edata
0000000000200398 g     F .flat  0000000000000000              szout
00000000002003a8 g       .flat  0000000000000000              _end
00000000002003a3 g       .flat  0000000000000000              __bss_start    

I'm running out of ideas here. Any progress on your end?
Post 23 Nov 2014, 00:47
View user's profile Send private message Reply with quote
evk1



Joined: 18 Jun 2014
Posts: 24
evk1
Hi. Sorry for long delay. I have too little free time now.
Well, Of course your code is correct, but for unknown reason FASM generates incorrect object file for it. I didn't know why it is incorrect and in order to understand it I wrote 2 similar programs.
Code:
;FASM code
format ELF64
extrn puts
public func1
section '.text' executable
func1:call puts
ret    

Code:
;gas code
.text
.globl func1
.type func1, @function
func1:
call puts
ret
.size func1, .-func1    

The base difference between their object files is in relocation sections.

FASM output:
Code:
Relocation section '.rela.text' at offset 0x46 contains 1 entries:

Offset       Info         Type          Sym. Value       Sym. Name + Addend

000000000001 000200000002 R_X86_64_PC32 0000000000000000 puts + 0    

gas output:
Code:
Relocation section '.rela.text' at offset 0x320 contains 1 entries:

Offset       Info         Type          Sym. Value       Sym. Name + Addend

000000000001 000500000002 R_X86_64_PC32 0000000000000000 puts - 4
    


So to call a function gas intends to put an offset of function - 4 to instruction address field. I think it is required by processor.
I haven't met such problems because such relocations usually appears only in relocatable files. Output libraries and programs usually use relocations only to put external function and data addresses to some their internal variables and then use these variables to make an indirect function call.

I tried to use call puts-4, but readelf showed the same relocation section content:
Code:
Relocation section '.rela.text' at offset 0x46 contains 1 entries:

Offset       Info         Type          Sym. Value       Sym. Name + Addend

000000000001 000200000002 R_X86_64_PC32 0000000000000000 puts + 0    


Consequently, FASM cannot correctly define an addend relocation field. I think it is due to the fact x86_64 ELF version uses RELA structure to define relocations instead of REL. The REL structure allows to place an addend directly at the relocatable address, but if you use RELA you have to place an addend at the special RELA structure field. This situation seems like FASM uses RELA but still places addend at the relocatable location. It is very strange. It seems like FASM has a serious bug, but I have no other ideas.

_________________
Sorry for my English
Post 25 Nov 2014, 20:53
View user's profile Send private message Reply with quote
eilenbeb



Joined: 17 Feb 2010
Posts: 21
eilenbeb
Fasm -is- creating the 'Addend' field, it's just filling it in with zeros. I just used a hex editor to modify that field, and now 'call plt puts' works as expected.
My reloc table is of type .rela.flat (at the moment) But i've seen other rela types during my experiments.
Code:
readelf -a ./libmisc.o
-snip-
Relocation section '.rela.flat' at offset 0x4c contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000002  000200000002 R_X86_64_PC32     0000000000000000 puts - 4
000000000007  000200000002 R_X86_64_PC32     0000000000000000 puts + 0
-snip-    
In 64bit, the size of the 'Addend' field is 64bits, and it's at the very end of each entry.
It shouldn't be too hard to write a 'fixup' program to patch the .o file before passing it to ld.
I just gotta learn how to read the headers better so I can -find- the '.rela.flat' table, heh.

-edit- Just wrote a 'fixup' prog that adjusts the Addend field in the .o file before running ld. Seems to be working, but I know it isn't 'correct' yet. I need to get ahold of the ELF specs and make sure I'm not doing anything hack-ish.
My little test lib now exports two funcs and imports 5 from 2 external libs. All the calls now go where they're supposed to.
Post 30 Nov 2014, 22:19
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7755
Location: Kraków, Poland
Tomasz Grysztar
Yes, there is a serious bug here. I think I already knew about it but it got forgotten for some reason. I'm fixing it right now. Please try the 1.71.28 version and let me know if this solves the problem.
Post 01 Dec 2014, 10:55
View user's profile Send private message Visit poster's website Reply with quote
eilenbeb



Joined: 17 Feb 2010
Posts: 21
eilenbeb
Hey Tomasz. Sorry but I just got busy again. Might be a couple of days before I can test v28.

-edit-
Ok, I tested v28 (in 64bit only) and it appears to be working. Nice job. Marking as solved.
Post 01 Dec 2014, 22:25
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7755
Location: Kraków, Poland
Tomasz Grysztar
The correction was still incomplete, version 1.71.30 has the final fix.
Post 07 Dec 2014, 13:15
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on YouTube, Twitter.

Website powered by rwasa.