LINUX.ORG.RU

функция main() в библиотеке


0

1

Хочу сделать сабж ради красноглазия, ведь с /lib/libc.so.6 работает. Однако при добавлении -shared сразу сегфолт происходит при попытке запуска. Чегой-то оно не хочет работать?

LOR$ cat ./test.c 
#include <stdio.h>
#include <stdlib.h>


int main(void) {
    printf("hello, Hell!!\n");
    return 0;
}
LOR$ gcc  ./test.c -o test && ./test 
hello, Hell!!
LOR$ gcc -shared  ./test.c -o test && ./test 
Segmentation fault
LOR$ 
★★★★★

Хедер /lib/libc.so.6:

Program Header:
    PHDR off    0x0000000000000040 vaddr 0x0000000000000040 paddr 0x0000000000000040 align 2**3
         filesz 0x0000000000000230 memsz 0x0000000000000230 flags r-x
  INTERP off    0x0000000000123300 vaddr 0x0000000000123300 paddr 0x0000000000123300 align 2**4
         filesz 0x000000000000001a memsz 0x000000000000001a flags r--
    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21
         filesz 0x00000000001526c0 memsz 0x00000000001526c0 flags r-x
    LOAD off    0x0000000000152710 vaddr 0x0000000000352710 paddr 0x0000000000352710 align 2**21
         filesz 0x0000000000004688 memsz 0x0000000000009458 flags rw-
 DYNAMIC off    0x0000000000155b40 vaddr 0x0000000000355b40 paddr 0x0000000000355b40 align 2**3
         filesz 0x00000000000001f0 memsz 0x00000000000001f0 flags rw-
    NOTE off    0x0000000000000270 vaddr 0x0000000000000270 paddr 0x0000000000000270 align 2**2
         filesz 0x0000000000000020 memsz 0x0000000000000020 flags r--
     TLS off    0x0000000000152710 vaddr 0x0000000000352710 paddr 0x0000000000352710 align 2**3
         filesz 0x0000000000000010 memsz 0x0000000000000068 flags r--
EH_FRAME off    0x000000000012331c vaddr 0x000000000012331c paddr 0x000000000012331c align 2**2
         filesz 0x000000000000661c memsz 0x000000000000661c flags r--
   STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**3
         filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
   RELRO off    0x0000000000152710 vaddr 0x0000000000352710 paddr 0x0000000000352710 align 2**0
         filesz 0x00000000000038f0 memsz 0x00000000000038f0 flags r--

Хедер хелловорлда без shared:

Program Header:
    PHDR off    0x0000000000000040 vaddr 0x0000000000400040 paddr 0x0000000000400040 align 2**3
         filesz 0x00000000000001c0 memsz 0x00000000000001c0 flags r-x
  INTERP off    0x0000000000000200 vaddr 0x0000000000400200 paddr 0x0000000000400200 align 2**0
         filesz 0x000000000000001a memsz 0x000000000000001a flags r--
    LOAD off    0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**21
         filesz 0x000000000000067c memsz 0x000000000000067c flags r-x
    LOAD off    0x0000000000000680 vaddr 0x0000000000600680 paddr 0x0000000000600680 align 2**21
         filesz 0x0000000000000208 memsz 0x0000000000000218 flags rw-
 DYNAMIC off    0x00000000000006a8 vaddr 0x00000000006006a8 paddr 0x00000000006006a8 align 2**3
         filesz 0x00000000000001a0 memsz 0x00000000000001a0 flags rw-
    NOTE off    0x000000000000021c vaddr 0x000000000040021c paddr 0x000000000040021c align 2**2
         filesz 0x0000000000000020 memsz 0x0000000000000020 flags r--
EH_FRAME off    0x00000000000005dc vaddr 0x00000000004005dc paddr 0x00000000004005dc align 2**2
         filesz 0x0000000000000024 memsz 0x0000000000000024 flags r--
   STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**3
         filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-

С shared:

Program Header:
    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21
         filesz 0x0000000000000624 memsz 0x0000000000000624 flags r-x
    LOAD off    0x0000000000000628 vaddr 0x0000000000200628 paddr 0x0000000000200628 align 2**21
         filesz 0x0000000000000200 memsz 0x0000000000000210 flags rw-
 DYNAMIC off    0x0000000000000650 vaddr 0x0000000000200650 paddr 0x0000000000200650 align 2**3
         filesz 0x0000000000000190 memsz 0x0000000000000190 flags rw-
EH_FRAME off    0x00000000000005d4 vaddr 0x00000000000005d4 paddr 0x00000000000005d4 align 2**2
         filesz 0x0000000000000014 memsz 0x0000000000000014 flags r--
   STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**3
         filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-

anon_666
()

а де тут main:

$ readelf -a /lib/libc.so.6 | grep "FUNC.*GLOBAL.*main"
    18: 000e2af0    31 FUNC    GLOBAL DEFAULT   11 __getdomainname_chk@@GLIBC_2.4
   416: 000c6200   110 FUNC    GLOBAL DEFAULT   11 getdomainname@@GLIBC_2.0
   601: 0005fcb0    60 FUNC    GLOBAL DEFAULT   11 _IO_switch_to_main_wget_a@@GLIBC_2.2
  2190: 00016ad0   437 FUNC    GLOBAL DEFAULT   11 __libc_start_main@@GLIBC_2.0
  2230: 000c6270    61 FUNC    GLOBAL DEFAULT   11 setdomainname@@GLIBC_2.0

quasimoto ★★★★
()
Ответ на: комментарий от rg-400

не видел такого, через гугл вообще ничего не могу найти по этой теме.

Попробую прочитать как вообще запуск прог происходит...

true_admin ★★★★★
() автор топика
Ответ на: комментарий от quasimoto

а де тут main

An ELF object may also specify an entry point of the program, that is, the
virtual memory location that assumes control of the program. ...

From /usr/include/elf.h

typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf32_Half    e_type;                 /* Object file type */
  Elf32_Half    e_machine;              /* Architecture */
  Elf32_Word    e_version;              /* Object file version */
  Elf32_Addr    e_entry;                /* Entry point virtual address */
  Elf32_Off     e_phoff;                /* Program header table file offset */
  Elf32_Off     e_shoff;                /* Section header table file offset */
  Elf32_Word    e_flags;                /* Processor-specific flags */
  Elf32_Half    e_ehsize;               /* ELF header size in bytes */
  Elf32_Half    e_phentsize;            /* Program header table entry size */
  Elf32_Half    e_phnum;                /* Program header table entry count */
  Elf32_Half    e_shentsize;            /* Section header table entry size */
  Elf32_Half    e_shnum;                /* Section header table entry count */
  Elf32_Half    e_shstrndx;             /* Section header string table index */
} Elf32_Ehdr;

Она не нужна.

anon_666
()
Ответ на: комментарий от anon_666

да, но т.к. я использую линкер он вызывает _start. Т.е. хочу я этого или нет но мне его использовать придётся.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от edigaryev

спасибо, как раз искал эту доку. К сожалению это на грани моего понимания, но я попробую.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от edigaryev

мне не нравится то что они там избавляются от libc который у меня используется. Даже если я сделаю _start у меня же libc не будет инициализирована :(. Сижу читаю каменты в libc/sysdeps/i386/elf/start.S ...

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin
gcc -shared  test.c -o test.so

Смотрим:

gdb test.so
disas main

Выставляем точку входа:

./make-so-exec test.so <<entry_offset>>

Где make-so-exec это программка:

/*
 * Little pragma to make shared libraries be executable.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include <elf.h>

// chose one:
typedef Elf32_Ehdr Elf_Ehdr;
//typedef Elf64_Ehdr Elf_Ehdr;
typedef Elf32_Addr Elf_Addr;
//typedef Elf64_Addr Elf_Addr;

int
main (int argc, char *argv[]) {

    if ((argc < 3) || (argc > 3)) {
        fprintf (stderr, "Usage: ./make-so-exec <file.so> <entry-address>\n");
        return 1;
    }

    FILE *file = fopen(argv[1], "r+");
    Elf_Addr entry = atoi(argv[2]);

    Elf_Ehdr *elf_header = (Elf_Ehdr*)malloc(sizeof(Elf_Ehdr));
    fread(elf_header, sizeof(Elf_Ehdr), 1, file);
    elf_header->e_entry = entry;
    fseek (file, 0, SEEK_SET);
    fwrite(elf_header, sizeof(Elf_Ehdr), 1, file);

    fflush(file);
    fclose(file);

    return 0;
}

Наверно есть какая-то специальная GNU-тая утилита для этого ;)

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

Можно кстати и без gdb:

readelf -a test.so | grep main
readelf -h main | grep Entry

только нужно учесть что может быть смещение между адресом main и необходимой точкой входа - нужно посмотреть какое оно в других эльфах (какая-то константа).

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

ааа, хитро, прям в хедере поправить. тока не выходит :(. Может какая-нить секьюрити-фича мешает? А может всё дело в printf который без инициализации libc работать не будет... Уф, завтра ещё посижу.


LOR$ cat ./test.c 
#include <stdio.h>
#include <stdlib.h>


int main(void) {
    printf("hello, Hell!!\n");
    return 0;
}
LOR$ gcc -fPIC ./test.c -o test.so
LOR$ gdb ./test.so

(gdb) disassemble main
Dump of assembler code for function main:
0x080483e4 <main+0>:    push   %ebp
0x080483e5 <main+1>:    mov    %esp,%ebp
0x080483e7 <main+3>:    and    $0xfffffff0,%esp
0x080483ea <main+6>:    push   %ebx
0x080483eb <main+7>:    sub    $0x1c,%esp
0x080483ee <main+10>:   call   0x8048414 <__i686.get_pc_thunk.bx>
0x080483f3 <main+15>:   add    $0x1c01,%ebx
[...]
LOR$ ./make-so-exec  test.so 0x080483e4
LOR$ ./test.so 
Segmentation fault
true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

Давай лучше завтра ;) - там нужно 0x080483e4 в 10-ное представление загнать (atoi потому что) и вычесть офсет о котором я говорил.

quasimoto ★★★★
()
Ответ на: комментарий от anon_666

Ну это понятно, на скорую руку запостил первый вариант.

quasimoto ★★★★
()
Ответ на: комментарий от edigaryev

чорт, сделал так как там, оно почему-то вылетает на call main с invalid instruction. Ты в ассемблере сечёшь, можешь помочь?

true_admin ★★★★★
() автор топика
const char interpreter[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
 
void hello(void)
{
    puts("Hello");
    exit(0);
}
$ gcc -fpic -shared -Wl,-e,hello -o hello.so hello.c
$ ./hello.so
Hello
$
unsigned ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.