Re: Functions and Global Variables defined in Libraries

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Mar 7, 2023 at 1:05 PM Xi Ruoyao wrote:
>
>
> > (2) Is there any way to stop the GNU linker from putting an undefined
> > function in R_X86_64_GLOB_DAT?
>
> No, unless you avoid extracting its address.


I've been doing some major tinkering today.

The entry point of an executable is '_start'. So, first I wrote a new
entry point in x64 assembler that could differentiate between GUI mode
and console mode depending upon the value of 'argc':

; This file contains x86_64 assembler for NASM, also known as x64.
; This file contains two functions:
; static void print8bytes(uint64_t eight_chars,uint64_t new_line);
; extern void pre_start(int argc);

section .text

print8bytes: ; This is a function that returns void
; Two parameters:
; r9: The 8-byte string to print
; r8: If true, prints a trailing new line

; save all the register values we're going to use
push rax
push rsi
push rdi
push rdx

;zero out the registers we are going to need
xor rax, rax
xor rsi, rsi
xor rdi, rdi
xor rdx, rdx

;write(int fd, char *msg, unsigned int len)
mov al, 1
add di, 1
mov rsi, r9
push rsi
mov rsi, rsp
mov dl, 8 ; Print 8 bytes at a time
syscall
pop rsi

cmp r8, 1 ; check if r8 is true or false
jl no_new_line
;zero out the registers we are going to need
xor rax, rax
xor rsi, rsi
xor rdi, rdi
xor rdx, rdx
;write(int fd, char *msg, unsigned int len)
mov al, 1
add di, 1
mov rsi, 0x000000000000000a ; new line
push rsi
mov rsi, rsp
mov dl, 1 ; Print just one byte
syscall
pop rsi
no_new_line: ; just a jump label - not a function name
pop rdx
pop rdi
pop rsi
pop rax
ret

global pre_start:function
pre_start:
; The 'argc' argument to 'main' is on the top of the stack so
; we will use the frame pointer 'rbp' to keep track of it.
push rbp
mov rbp, rsp

push r9 ; save because we'll use it - pop it back later
push r8 ; save because we'll use it - pop it back later

mov r8, 0 ; false = don't put trailing new line
mov r9, 0x3d3d3d3d3d3d3d3d ; "========"
call print8bytes
call print8bytes
call print8bytes

mov r9, 0x6174735f65727020 ; " pre_sta"
call print8bytes

cmp qword[rbp+8], 2 ; check if argc < 2
jl $+2+10+2 ; if argc < 2 then we want GUI mode
mov r9, 0x646d63202d207472 ; "rt - cmd"
jmp $+2+10 ; skip the next 10-byte instruction
mov r9, 0x495547202d207472 ; "rt - GUI"
call print8bytes

mov r9, 0x3d3d3d3d3d3d3d3d ; "========"
call print8bytes
call print8bytes
mov r8, 1 ; true = put trailing new line
call print8bytes

pop r8
pop r9

mov rsp, rbp
pop rbp

extern _start
jmp _start


If you see the last line there, I jump straight into _start. So then I
build my program with a new entry point as follows:

    g++ -o prog prog.cpp object_file_from_assembler.o -e pre_start

When I run it at the command line, the first thing I get is:

    ======================== pre_start - GUI========================

and then it continues execution as normal. No problems.

So then the next thing I did was I used 'patchelf' to remove the
NEEDED for the graphical user interface library:

    patchelf --remove-needed libgtk-3.so.0 ./prog

And then I tried to run it again, but this time around I got back:

    ./ssh: symbol lookup error: ./ssh: undefined symbol: gtk_true

This means that the program falls over ***before*** the entry point is reached.

So the part of the Linux operating system that loads executable files
is not even going into the entry point for my program, it's falling
over before then. I need to stop this happening some how. Perhaps I
can put dummy values in the GOT table so that the loader doesn't think
they're null?

On Tue, Mar 7, 2023 at 1:25 PM Alexander Monakov <amonakov@xxxxxxxxx> wrote:
>
>
> On Tue, 7 Mar 2023, Xi Ruoyao via Gcc-help wrote:
>
> > This won't work for a function pointer either: the value of the
> > function pointer must be the address of foo itself, not foo@plt.  Or the
> > result of &foo in the shared library and the main executable will be
> > different, violating the C or C++ standard.  Then we must use
> > R_X86_64_JUMP_SLOT which is handled by the dynamic linker.
>
> (you probably meant GLOB_DAT in the last statement)
>
> This paragraph is inaccurate: traditional non-PIC, non-PIE codegen uses
> direct symbol references. So, when you have a direct reference to foo
> in non-PIC main executable, the reference is resolved to its PLT slot,
> and the address of that PLT slot becomes the canonical address of 'foo'
> for the whole program.
>
> When the main executable is PIE, it may or may not have a PLT slot for
> 'foo', and if it doesn't, the canonical address of 'foo' is its actual
> implementation.
>
> Alexander




[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux