Implement dynamic linking with system libraries via -lsyslibname:

console.obj
http.ibj
InputBox.obj
Add header files for apps what dynamically link these libraries.


git-svn-id: svn://kolibrios.org@7925 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Magomed Kostoev (mkostoevr) 2020-05-16 08:07:10 +00:00
parent 67dc3cd6fc
commit 90cf9246ac
46 changed files with 1146 additions and 19 deletions

View File

@ -0,0 +1,9 @@
format ELF
include '__lib__.inc'
section '.text'
public lib_name
lib_name db 0x55, 0xAA, lib_name_str, 0

View File

@ -0,0 +1,2 @@
lib_name equ @console.obj
lib_name_str equ '/sys/lib/console.obj'

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_cls
fun_str equ 'con_cls'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_exit
fun_str equ 'con_exit'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_get_cursor_height
fun_str equ 'con_get_cursor_height'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_get_cursor_pos
fun_str equ 'con_get_cursor_pos'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_get_flags
fun_str equ 'con_get_flags'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_get_font_height
fun_str equ 'con_get_font_height'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_getch
fun_str equ 'con_getch'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_getch2
fun_str equ 'con_getch2'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_gets
fun_str equ 'con_gets'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_gets2
fun_str equ 'con_gets2'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_init
fun_str equ 'con_init'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_kbhit
fun_str equ 'con_kbhit'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_printf
fun_str equ 'con_printf'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_set_cursor_pos
fun_str equ 'con_set_cursor_pos'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_set_flags
fun_str equ 'con_set_flags'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_set_title
fun_str equ 'con_set_title'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_write_asciiz
fun_str equ 'con_write_asciiz'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ con_write_string
fun_str equ 'con_write_string'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,22 @@
fasm __lib__.asm
fasm con_write_asciiz.asm
fasm con_write_string.asm
fasm con_init.asm
fasm con_exit.asm
fasm con_set_title.asm
fasm con_printf.asm
fasm con_get_flags.asm
fasm con_set_flags.asm
fasm con_get_font_height.asm
fasm con_get_cursor_height.asm
fasm con_getch.asm
fasm con_getch2.asm
fasm con_kbhit.asm
fasm con_gets.asm
fasm con_gets2.asm
fasm con_cls.asm
fasm con_get_cursor_pos.asm
fasm con_set_cursor_pos.asm
kos32-ar -ru libconsole.a *.o
del *.o
pause

View File

@ -0,0 +1,9 @@
format ELF
include '__lib__.inc'
section '.text'
public lib_name
lib_name db 0x55, 0xAA, lib_name_str, 0

View File

@ -0,0 +1,2 @@
lib_name equ @http.obj
lib_name_str equ '/sys/lib/http.obj'

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ get
fun_str equ 'get'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ head
fun_str equ 'head'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,9 @@
fasm __lib__.asm
fasm get.asm
fasm head.asm
fasm post.asm
fasm receive.asm
fasm send.asm
kos32-ar -ru libhttp.a *.o
del *.o
pause

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ post
fun_str equ 'post'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ receive
fun_str equ 'receive'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ send
fun_str equ 'send'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ InputBox
fun_str equ 'InputBox'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,9 @@
format ELF
include '__lib__.inc'
section '.text'
public lib_name
lib_name db 0x55, 0xAA, lib_name_str, 0

View File

@ -0,0 +1,2 @@
lib_name equ @inputbox.obj
lib_name_str equ '/sys/lib/inputbox.obj'

View File

@ -0,0 +1,5 @@
fasm __lib__.asm
fasm InputBox.asm
kos32-ar -ru libinputbox.a *.o
del *.o
pause

View File

@ -0,0 +1,9 @@
format ELF
include '__lib__.inc'
section '.text'
public lib_name
lib_name db 0x55, 0xAA, lib_name_str, 0

View File

@ -0,0 +1,2 @@
lib_name equ @sample.obj
lib_name_str equ '/sys/lib/sample.obj'

View File

@ -0,0 +1,13 @@
Create new library wrapper
1. Redefine lib_name and lib_name_str in __lib__.inc
2. Create file for each symbol, basing on sample_symbol.asm and for each:
2.1. Redefine fun to *your_symbol_name*
2.2. Redefine fun_name to '*your_symbol_name*' (with quotes, this is ASCII string, no trailing zero need)
3. Change make.bat as appropriate
ACHTUNG: lib_name need to be unique in project, this is why I started it with "@" and put "." into.
ACHTUNG: lib_name_str must be at least 5 symbols long, if is not, fix this adding padding to the path.
Now you can create header file and declare extern variables pointers-to-functions, and then link your app with -llibname (put .a file in lib folder).
For examples of such header files, look at include/kos/inputbox.h, include/kos/console.h and include/kos/http.h. IMO, first one is the simplest.

View File

@ -0,0 +1,5 @@
fasm __lib__.asm
fasm sample_symbol.asm
kos32-ar -ru libsample.a *.o
del *.o
pause

View File

@ -0,0 +1,18 @@
format ELF
include "__lib__.inc"
fun equ sample_symbol
fun_str equ 'sample_symbol'
section '.text'
fun_name db fun_str, 0
section '.data'
extrn lib_name
public fun
fun dd fun_name
lib dd lib_name

View File

@ -0,0 +1,183 @@
/*
This is adapded thunk for console.obj sys library
.h is equal to svn:\programs\develop\libraries\console\console_en.txt
Adapted for tcc by Siemargl, 2016
Adapted for dynamic API by Magomed Kostoev, 2020 (just copied this, actually =P)
*/
#ifndef __dylibc__kos__console_h__
#define __dylibc__kos__console_h__
#define cdecl __attribute__ ((cdecl))
#define stdcall __attribute__ ((stdcall))
/*
console.obj exports the following functions
*/
extern void stdcall (*con_init)(unsigned int wnd_width, unsigned int wnd_height,
unsigned int scr_width, unsigned int scr_height, const char* title);
/* Console initialization. Must be called only once.
wnd_width, wnd_height - width and height (in units of characters) of the visible
region;
scr_width, scr_height - width and height (in units of characters) of console;
Any of these four parameters can be set to -1 (=0xFFFFFFFF)
to use the library's default values;
title - console window's caption. */
extern void stdcall (*con_exit)(int bCloseWindow);
/* You should call this funstion at the end of the program.
If bCloseWindow is zero, the string "[Finished]" will be added to the caption of
the window and the console window will remain on the screen until the user
closes it. */
extern void stdcall (*con_set_title)(const char* title);
/* Set new window caption. */
extern void stdcall (*con_write_asciiz)(const char* str);
/* Display ASCIIZ-string to the console at the current position, shifting
the current position. */
extern void stdcall (*con_write_string)(const char* str, unsigned int length);
/* Similar to con_write_asciiz, but length of the string must be given as a
separate parameter */
extern int cdecl (*con_printf)(const char* format, ...);
/* Standard "printf" function from ANSI C. */
extern unsigned int stdcall (*con_get_flags)(void);
/* Get output flags. */
extern unsigned int stdcall (*con_set_flags)(unsigned int new_flags);
/* Set output flags. This function returns previous values. */
/* Flags (bitmask): */
/* text color */
#define CON_COLOR_BLUE 0x01
#define CON_COLOR_GREEN 0x02
#define CON_COLOR_RED 0x04
#define CON_COLOR_BRIGHT 0x08
/* background color */
#define CON_BGR_BLUE 0x10
#define CON_BGR_GREEN 0x20
#define CON_BGR_RED 0x40
#define CON_BGR_BRIGHT 0x80
/* output controls */
#define CON_IGNORE_SPECIALS 0x100
/* if this flag is cleared, function interprets special characters:
10 ('\n') - next line
13 ('\r') - carriage return
8 ('\b') - backspace
9 ('\t') - tab
27 ('\033' = '\x1B') - the beginning of Esc-sequences;
otherwise, these characters will be displayed like ordinary characters. */
/* Supported Esc-sequences:
Esc[<number1>;<number2>;<number3>m - choice of character attributes:
You can specify one, two or three codes in any order;
0 = normal mode (white on black)
1 = bright selection
5 = bright background
7 = inverse mode (black on white)
30 = black characters
31 = red characters
32 = green characters
33 = brown characters
34 = blue characters
35 = purple characters
36 = turqoise characters
37 = white characters
40 = black background
41 = red background
42 = green background
43 = brown background
44 = blue background
45 = purple background
46 = turqoise background
47 = white background
The following sequences appeared in version 5 of library:
Esc[2J - clear screen, move cursor to upper left corner
Esc[<number1>;<number2>H = Esc[<number1>;<number2>f -
move cursor to <number1>,<number2>
Esc[<number>A - move cursor to <number> lines up
Esc[<number>B - move cursor to <number> lines down
Esc[<number>C - move cursor to <number> positions right
Esc[<number>D - move cursor to <number> positions left
*/
/* signal "console closed"; appeared in version 6;
ignored by con_set_flags */
#define CON_WINDOW_CLOSED 0x200
/* The default value for flags = 7. (grey text on black background) */
extern int stdcall (*con_get_font_height)(void);
/* Get the height of the font. */
extern int stdcall (*con_get_cursor_height)(void);
/* Get the height of the cursor. */
extern int stdcall (*con_set_cursor_height)(int new_height);
/* Set the height of the cursor. This function returns previous value.
An attempt to set the value out of the correct interval (from 0 to
font_height-1) is ignored.
Cursor with zero height isn't displayed.
Default value: - 15% from font height. */
extern int stdcall (*con_getch)(void);
/* Get one character from the keyboard.
For normal characters function returns ASCII-code. For extended
characters (eg, Fx, and arrows), first function call returns 0
and second call returns the extended code (similar to the DOS-function
input). Starting from version 7, after closing the console window,
this function returns 0. */
extern unsigned short stdcall (*con_getch2)(void);
/* Reads a character from the keyboard. Low byte contains the ASCII-code
(0 for extended characters), high byte - advanced code (like in BIOS
input functions). Starting from version 7, after closing the console
window, this function returns 0. */
extern int stdcall (*con_kbhit)(void);
/* Returns 1 if a key was pressed, 0 otherwise. To read pressed keys use
con_getch and con_getch2. Starting from version 6, after closing
the console window, this function returns 1. */
extern char* stdcall (*con_gets)(char* str, int n);
/* Reads a string from the keyboard. Reading is interrupted when got
"new line" character, or after reading the (n-1) characters (depending on
what comes first). In the first case the newline is also recorded in the
str. The acquired line is complemented by a null character.
Starting from version 6, the function returns a pointer to the entered
line if reading was successful, and NULL if the console window was closed. */
typedef int (stdcall * con_gets2_callback)(int keycode, char** pstr, int* pn,
int* ppos);
extern char* stdcall (*con_gets2)(con_gets2_callback callback, char* str, int n);
/* Con_gets completely analogous, except that when the user
press unrecognized key, it calls the specified callback-procedure
(which may, for example, handle up / down for history and tab to enter
autocompletion). You should pass to the procedure: key code and three pointers
- to the string, to the maximum length and to the current position.
function may change the contents of string and may change the string
itself (for example, to reallocate memory for increase the limit),
maximum length, and position of the line - pointers are passed for it.
Return value: 0 = line wasn't changed 1 = line changed, you should
remove old string and display new, 2 = line changed, it is necessary
to display it; 3 = immediately exit the function.
Starting from version 6, the function returns a pointer to the entered
line with the successful reading, and NULL if the console window was closed. */
extern void stdcall (*con_cls)();
/* Clear screen and set cursor at upper left corner. */
extern void stdcall (*con_get_cursor_pos)(int* px, int* py);
/* Wrote current (x) coordinate of cursor to *px, and (y) to *py. */
extern void stdcall (*con_set_cursor_pos)(int x, int y);
/* Set the cursor position to the specified coordinates. If any of the
parameters beyond the relevant range (from 0 to 1 scr_width-
for x, from 0 to 1 for scr_height-y, scr_width scr_height and were asked if
call con_init), then the corresponding coordinate of the cursor does not change.
*/
#endif

View File

@ -0,0 +1,139 @@
/*
This is adapded thunk for console.obj sys library
.h is equal to svn:\programs\develop\libraries\http\http_en.txt
Adapted for TCC's dynamic API by Magomed Kostoev, 2020
*/
#ifndef __kos__http__h________
#define __kos__http__h________
#define cdecl __attribute__ ((cdecl))
#define stdcall __attribute__ ((stdcall))
// Bitflags for http_msg.flags
// status
#define HTTP_FLAG_HTTP11 1 << 0
#define HTTP_FLAG_GOT_HEADER 1 << 1
#define HTTP_FLAG_GOT_ALL_DATA 1 << 2
#define HTTP_FLAG_CONTENT_LENGTH 1 << 3
#define HTTP_FLAG_CHUNKED 1 << 4
#define HTTP_FLAG_CONNECTED 1 << 5
// user options
#define HTTP_FLAG_KEEPALIVE 1 << 8
#define HTTP_FLAG_STREAM 1 << 9
#define HTTP_FLAG_REUSE_BUFFER 1 << 10
#define HTTP_FLAG_BLOCK 1 << 11
// error
#define HTTP_FLAG_INVALID_HEADER 1 << 16
#define HTTP_FLAG_NO_RAM 1 << 17
#define HTTP_FLAG_SOCKET_ERROR 1 << 18
#define HTTP_FLAG_TIMEOUT_ERROR 1 << 19
#define HTTP_FLAG_TRANSFER_FAILED 1 << 20
/*
User flags:
For the flag codes themselves, see http.inc file.
FLAG_KEEPALIVE will keep the connection open after first GET/POST/.. so you can send a second request on the same TCP session.
In this case, the session must be closed manually when done by using the exported disconnect() function.
FLAG_STREAM will force receive() to put the received content in a series of fixed size buffers, instead of everything in one big buffer.
This can be used for example to receive an internet radio stream,
but also to download larger files for which it does not make sense to put them completely in RAM first.
FLAG_REUSE_BUFFER is to be used in combination with FLAG_STREAM and will make receive() function re-use the same buffer.
This, for example, can be used when downloading a file straight to disk.
FLAG_BLOCK will make receive() function blocking. This is only to be used when receiving one file from a thread that has no other work.
If however, you want to receive multiple files, or do other things in the program mainloop, you should call the receive function periodically.
You may use system function 10 or 23 to wait for network event before calling one or more receive() functions.
*/
typedef struct http_msg_s {
unsigned socket; // socket on which the actual transfer happens
unsigned flags; // flags, reflects status of the transfer using bitflags
unsigned write_ptr; // internal use only (where to write new data in buffer)
unsigned buffer_length; // internal use only (number of available bytes in buffer)
unsigned chunk_ptr; // internal use only (where the next chunk begins)
unsigned timestamp; // internal use only (when last data was received)
unsigned status; // HTTP status
unsigned header_length; // length of HTTP header
void * content_ptr; // ptr to content
unsigned content_length; // total length of HTTP content
unsigned content_received; // number of currently received content bytes
char http_header[1];
} http_msg;
/*
url = pointer to ASCIIZ URL
identifier = identifier of previously opened connection (keep-alive), or 0 to open a new one.
flags = bit flags (see end of this document).
add_header = pointer to ASCIIZ additional header parameters, or null for none.
Every additional parameter must end with CR LF bytes, including the last line.
Initiates a HTTP connection, using 'GET' method.
Returns NULL on error, identifier otherwise.
*/
extern http_msg * stdcall (*get)(const char *url, http_msg *identifier, unsigned flags, const char *add_header);
/*
url = pointer to ASCIIZ URL
identifier = identifier of previously opened connection (keep-alive), or 0 to open a new one.
flags = bit flags (see end of this document).
add_header = pointer to ASCIIZ additional header parameters, or null for none.
Every additional parameter must end with CR LF bytes, including the last line.
Initiate a HTTP connection, using 'HEAD' method.
Returns NULL on error, identifier otherwise.
*/
extern http_msg * stdcall (*head)(const char *url, http_msg *identifier, unsigned flags, const char *add_header);
/*
url = pointer to ASCIIZ URL
identifier = identifier of previously opened connection (keep-alive), or 0 to open a new one.
flags = bit flags (see end of this document).
add_header = pointer to ASCIIZ additional header parameters, or null for none.
Every additional parameter must end with CR LF bytes, including the last line.
content-type = pointer to ASCIIZ string containing content type.
content-length = length of the content (in bytes).
Initiate a HTTP connection, using 'POST' method.
The content itself must be send to the socket (which you can find in the structure),
using system function 75, 6.
Returns 0 on error, identifier otherwise
*/
extern http_msg * stdcall (*post)(const char *url, http_msg *identifier, unsigned flags, const char *add_header,
const char *content_type, unsigned content_length);
/*
identifier = identifier which one of the previous functions returned
This procedure will handle all incoming data for a connection and place it in the buffer.
As long as the procedure expects more data, -1 is returned and the procedure must be called again.
When transfer is done, the procedure will return 0.
The receive procedure is non-blocking by default, but can be made to block by setting FLAG_BLOCK.
The HTTP header is placed together with some flags and other attributes in the http_msg structure.
This structure is defined in http.inc (and not copied here because it might still change.)
The identifier used by the functions is actually a pointer to this structure.
In the dword named .flags, the library will set various bit-flags indicating the status of the process.
(When a transfer is done, one should check these bit-flags to find out if the transfer was error-free.)
The HTTP header is placed at the end of this structure. The content is placed in another buffer.
The dword .status contains the status code received from the server (e.g. 200 for OK).
In header_length you'll find the length of the header as soon as it has been received.
In content_ptr you'll find a pointer to the actual content.
In content_length you'll find the length of the content.
In content_received, you'll find the number of content bytes already received.
*/
extern int stdcall (*receive)(http_msg *identifier);
/*
identifier = identifier which one of the previous functions returned
dataptr = pointer to the data you want to send
datalength = length of the data to send (in bytes)
This procedure can be used to send data to the server (POST)
Returns number of bytes sent, -1 on error
*/
extern int stdcall (*send)(http_msg *identifier, void *dataptr, unsigned datalength);
#endif // __kos__http__h________

View File

@ -0,0 +1,17 @@
/*
This is wrapper for Inputbox.obj sys library
https://board.kolibrios.org/viewtopic.php?f=24&t=3767&sid=fd2ca95b24eec430db0c61d977f5d8ba#p71585
Adapted for TCC's dynamic API by Magomed Kostoev, 2020
*/
#ifndef __KOS__INPUTBOX__H________
#define __KOS__INPUTBOX__H________
#define cdecl __attribute__ ((cdecl))
#define stdcall __attribute__ ((stdcall))
extern unsigned stdcall (*InputBox)(void* Buffer, char* Caption, char* Prompt, char* Default,
unsigned long Flags, unsigned long BufferSize, void* RedrawProc);
#endif // __KOS__INPUTBOX__H________

View File

@ -5,6 +5,9 @@ public start as '_start'
;extrn mf_init
extrn main
;include 'debug2.inc'
include '..\..\..\..\..\proc32.inc'
include '..\..\..\..\..\macros.inc'
include '..\..\..\..\..\dll.inc'
__DEBUG__=0
;start_:
@ -12,7 +15,7 @@ virtual at 0
db 'MENUET01' ; 1. Magic number (8 bytes)
dd 0x01 ; 2. Version of executable file
dd start ; 3. Start address
dd 0x0 ; 4. Size of image
imgsz dd 0x0 ; 4. Size of image
dd 0x100000 ; 5. Size of needed memory
dd 0x100000 ; 6. Pointer to stack
hparams dd 0x0 ; 7. Pointer to program arguments
@ -26,14 +29,7 @@ start:
mov ebx,11
int 0x40
;DEBUGF ' path "%s"\n params "%s"\n', .path, .params
; check for overflow
;; that not work
; mov al, [path+buf_len-1]
; or al, [params+buf_len-1]
; jnz .crash
; check if path written by OS
mov [argc], 0
mov [argc], 0
mov eax, [hparams]
test eax, eax
jz .without_path
@ -90,25 +86,16 @@ start:
jmp .parse
.run:
;DEBUGF 'call main(%x, %x) with params:\n', [argc], argv
if __DEBUG__ = 1
mov ecx, [argc]
@@:
lea esi, [ecx * 4 + argv-4]
DEBUGF '0x%x) "%s"\n', cx, [esi]
loop @b
end if
call load_imports
push argv
push [argc]
call main
.exit:
;DEBUGF 'Exit from prog\n';
xor eax,eax
dec eax
int 0x40
dd -1
.crash:
;DEBUGF 'E:buffer overflowed\n'
jmp .exit
;============================
push_param:
@ -127,6 +114,96 @@ push_param:
.dont_add:
ret
;==============================
;==============================
load_imports:
;==============================
;parameters
; none
;description
; imports must be located at end of image (but before BSS sections)
; the address of end of imports (next byte after imports) is located in imgsz
; look at each import from that address up to illegal import
; legal import is such that:
; first pointer points to procedure name
; and is smaller than imgsz
; second pointer points lo library name, starting with 0x55, 0xAA
; and is smaller than imgsz
; each library should be initialized as appropriate, once
; so as library is initialized, its name will be replaced 0x00
mov ebx, [imgsz] ; byte after imports
.handle_next_import:
sub ebx, 4 ; ebx = pointer to pointer to library name
mov esi, dword[ebx] ; esi = pointer to library name
push ebx
push esi
call load_library ; eax = pointer to library exports
pop esi
pop ebx
test eax, eax
jz .done
sub ebx, 4 ; ebx = pointer to pointer to symbol name
push ebx
stdcall dll.GetProcAddress, eax, dword[ebx]
pop ebx
test eax, eax
jz .fail
mov dword[ebx], eax
jmp .handle_next_import
.done:
ret
.fail:
ret
;==============================
;==============================
load_library:
;==============================
;parameters
; ebx: library name address
;description
; each library should be initialized as appropriate, once
; so as library is initialized, its name will be replaced 0x00
; and 4 next bytes will be set to address of library
; first two bytes of library name must be 0x55, 0xAA (is like a magic)
cld ; move esi further, not back
cmp esi, [imgsz]
ja .fail
lodsb ; al = first byte of library name
cmp al, 0x55
jne .fail
lodsb ; al = second byte of library name
cmp al, 0xAA
jne .fail
lodsb ; al = third byte of library name (0x00 if the library is already loaded)
test al, al
jnz .load
lodsd ; if we here, then third byte is 0x00 => address of library is in next 4 bytes
; now eax contains address of library
ret
.load:
dec esi ; we checked on 0 before, let's go back
mov eax, 68
mov ebx, 19
mov ecx, esi
int 0x40 ; eax = address of exports
mov byte[esi], 0 ; library is loaded, let's place 0 in first byte of name
mov [esi + 1], eax ; now next 4 bytes of library name are replaced by address of library
; call lib_init
stdcall dll.GetProcAddress, eax, lib_init_str ; eax = address of lib_init
test eax, eax
jz .ret
stdcall dll.Init, eax
.ret:
mov eax, [esi + 1] ; put address of library into eax
ret
.fail:
mov eax, 0
ret
;==============================
lib_init_str db 'lib_init', 0
public argc as '__argc'
public params as '__argv'
public path as '__path'

View File

@ -0,0 +1,143 @@
format ELF
section '.text' executable
public start
public start as '_start'
;extrn mf_init
extrn main
;include 'debug2.inc'
__DEBUG__=0
;start_:
virtual at 0
db 'MENUET01' ; 1. Magic number (8 bytes)
dd 0x01 ; 2. Version of executable file
dd start ; 3. Start address
dd 0x0 ; 4. Size of image
dd 0x100000 ; 5. Size of needed memory
dd 0x100000 ; 6. Pointer to stack
hparams dd 0x0 ; 7. Pointer to program arguments
hpath dd 0x0 ; 8. Pointer to program path
end virtual
start:
;DEBUGF 'Start programm\n'
;init heap of memory
mov eax,68
mov ebx,11
int 0x40
;DEBUGF ' path "%s"\n params "%s"\n', .path, .params
; check for overflow
;; that not work
; mov al, [path+buf_len-1]
; or al, [params+buf_len-1]
; jnz .crash
; check if path written by OS
mov [argc], 0
mov eax, [hparams]
test eax, eax
jz .without_path
mov eax, path
cmp word ptr eax, 32fh ; '/#3' UTF8
jne .without_path
mov word ptr eax, 12fh ; '/#1' fix to CP866
.without_path:
mov esi, eax
call push_param
; retrieving parameters
mov esi, params
xor edx, edx ; dl - èä¸ò ïàðàìåòð(1) èëè ðàçäåëèòåëè(0)
; dh - ñèìâîë ñ êîòîðîãî íà÷àëñÿ ïàðàìåòð (1 êàâû÷êè, 0 îñòàëüíîå)
mov ecx, 1 ; cl = 1
; ch = 0 ïðîñòî íîëü
.parse:
lodsb
test al, al
jz .run
test dl, dl
jnz .findendparam
;{åñëè áûë ðàçäåëèòåëü
cmp al, ' '
jz .parse ;çàãðóæåí ïðîáåë, ãðóçèì ñëåäóþùèé ñèìâîë
mov dl, cl ;íà÷èíàåòñÿ ïàðàìåòð
cmp al, '"'
jz @f ;çàãðóæåíû êàâû÷êè
mov dh, ch ;ïàðàìåòð áåç êàâû÷åê
dec esi
call push_param
inc esi
jmp .parse
@@:
mov dh, cl ;ïàðàìåòð â êàâû÷åêàõ
call push_param ;åñëè íå ïðîáåë çíà÷èò íà÷èíàåòñÿ êàêîé òî ïàðàìåòð
jmp .parse ;åñëè áûë ðàçäåëèòåëü}
.findendparam:
test dh, dh
jz @f ; áåç êàâû÷åê
cmp al, '"'
jz .clear
jmp .parse
@@:
cmp al, ' '
jnz .parse
.clear:
lea ebx, [esi - 1]
mov [ebx], ch
mov dl, ch
jmp .parse
.run:
;DEBUGF 'call main(%x, %x) with params:\n', [argc], argv
if __DEBUG__ = 1
mov ecx, [argc]
@@:
lea esi, [ecx * 4 + argv-4]
DEBUGF '0x%x) "%s"\n', cx, [esi]
loop @b
end if
push argv
push [argc]
call main
.exit:
;DEBUGF 'Exit from prog\n';
xor eax,eax
dec eax
int 0x40
dd -1
.crash:
;DEBUGF 'E:buffer overflowed\n'
jmp .exit
;============================
push_param:
;============================
;parameters
; esi - pointer
;description
; procedure increase argc
; and add pointer to array argv
; procedure changes ebx
mov ebx, [argc]
cmp ebx, max_parameters
jae .dont_add
mov [argv+4*ebx], esi
inc [argc]
.dont_add:
ret
;==============================
public argc as '__argc'
public params as '__argv'
public path as '__path'
section '.bss'
buf_len = 0x400
max_parameters=0x20
argc rd 1
argv rd max_parameters
path rb buf_len
params rb buf_len
;section '.data'
;include_debug_strings ; ALWAYS present in data section

View File

@ -3,4 +3,5 @@
../tcc consoleio.c /kolibrios/develop/tcc/lib/libck.a -o consoleio
../tcc files.c /kolibrios/develop/tcc/lib/libck.a -o files
../tcc winbasics.c /kolibrios/develop/tcc/lib/libck.a -o winbasics
../tcc dynamic.c -lconsole -lhttp -linputbox
exit

View File

@ -0,0 +1,19 @@
#include <kos/console.h>
#include <kos/http.h>
#include <kos/inputbox.h>
int main() {
con_set_title("Dynamicaly linked app");
con_write_asciiz("Wait, I'll ask you... when I'll done to fetch one site");
http_msg *h = get("http://boppan.org", 0, HTTP_FLAG_BLOCK, "");
if (!receive(h)) {
con_printf("%s\n", h->content_ptr);
} else {
con_write_asciiz("Danmit! Can't access to the page.");
}
char buffer[256];
InputBox(buffer, "Hay!", "How do you do?", "Everything sucks", 0, 256, 0);
con_write_asciiz(buffer);
con_exit(0);
return 0;
}