Re: Linking libraries?
- From: Frank Kotler <fbkotler@xxxxxxxxxxx>
- Date: Tue, 30 May 2006 08:42:32 -0400
Solar wrote:
....
extern _getenv
You've uncovered one of the dirty little secrets of the "portable" C language ! :) For ELF C, externals *don't* take the leading underscore.
The "_start" label has an underscore, but "main", "printf",... and "getenv" stay as is.
Once you've fixed that, you'll need to tell ld we're using libc. A simple "-lc" *ought* to do it, but by default, ld uses the wrong dynamic loader - /lib/ld-linux.so.1. We want /lib/ld-linux.so.2 (the former will cause a "no such file" error - just as if the program you just made didn't exist!) "-I" is a shorter alias for "--dynamic-loader", so...
ld -o path path.o -lc -I/lib/ld-linux.so.2
should put you on the right... path. :)
(you really want to name this thing just "path"?)
But there's no need to call a library to find an environment variable in a Linux program - they're right there on the stack. Easiest thing in the world...
Best,
Frank
; nasm -f elf showpath.asm
; ld -o showpath showpath.o
; [strip showpath]
section .text
global _start
_start:
; When the ELF loader loads us, command-line arguments,
; if any (there's always "argv[0]" - the program name),
; and the environment strings, are on the stack.
; Unlike a C "main" startup, we haven't been "call"ed,
; and there's been no "push ebp", so we start right off
; with "argc" at [esp]. Next ([esp + 4]) is a zero-terminated
; array of pointers to zero-terminated strings
; (command-line args), followed by a similar
; array of pointers to environment strings. No
; "count" is provided, so we have to watch for
; the terminating zero. To get directly to the
; environment variables, we start with the initial
; esp, add 4 to clear "argc", add 4 times "argc" to
; clear the command-line arguments, and another 4
; to clear the terminating zero. Thus:
mov eax, [esp] ; "argc"
; lea ebx, [esp + 8 + eax * 4]
; but we'd like to bump ebx at the *top* of our loop, so:
lea ebx, [esp + 4 + eax * 4]
..top:
add ebx, byte 4
mov esi, [ebx] ; get a pointer
test esi, esi ; watch for the end!
jz .not_found
cmp dword [esi], 'PATH' ; look for path
jnz .top
cmp byte [esi + 4], '=' ; better make sure there's
jnz .top ; not more...
call putz ; got it - print it
mov esi, newline
call putz
xor ebx, ebx ; return success
jmp short .exit
..not_found:
or ebx, byte -1 ; return failure
..exit
mov eax, 1
int 80h
;-----------------------
;-----------------------
; expects: esi -> zero-terminated string
; returns: nothing useful
putz:
pusha
mov eax, 4 ; sys_write (__NR_write)
mov ebx, 1 ; stdout
mov ecx, esi ; buffer
; length in edx
or edx, byte -1
..find_len:
cmp [ecx + edx + 1], byte 1
inc edx
jnc .find_len
int 80h
popa
ret
;-----------------------------
;-----------------------------
; this is "const" data, and should really go in
; a "readonly" section... ".text" will do, BUT!
; kernels 2.6.10 thru 2.6.16 or so require a
; writeable section last, or the loader (not
; your code) segfaults. So put it in ".data"
; for those kernels.
;section .data
newline db 10, 0
;--------------------------------
.
- References:
- Linking libraries?
- From: Solar
- Linking libraries?
- Prev by Date: Re: Linking libraries?
- Next by Date: Re: Linking libraries?
- Previous by thread: Re: Linking libraries?
- Index(es):